过滤分层对象嵌套XAML数据显示模板 [英] Filtering a hierarchical object displayed with nested xaml data templates

查看:178
本文介绍了过滤分层对象嵌套XAML数据显示模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法过滤出的显示在嵌套的XAML模板分层数据。

I'm having trouble filtering hierarchical data that's being displayed in nested xaml templates.

我有一个的ObservableCollection<富> FOOS ,说我在显示XAML。

I've got a ObservableCollection<Foo> Foos, that I'm displaying in XAML.

可以说,富如下:

class Foo
{
    public ObservableCollection<Bar> Bars;
}

class Bar
{
    public ObservableCollection<Qux> Quxes;
}

我用下面的XAML显示FOOS:

I'm displaying Foos with the following xaml:

<Grid>
    <Grid.Resources>
        <CollectionViewSource x:Key="MyCVS" Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.UnifiedSymbols}" Filter="MyCVS_Filter" />

        <DataTemplate x:Key="NestedTabHeaderTemplate">
            <TextBlock Text="{Binding Path=Name}"/>
        </DataTemplate>
        <DataTemplate x:Key="NestedTabContentTemplate">
            <ListBox ItemsSource="{Binding Path=Quxes}" DisplayMemberPath="Name"/>
        </DataTemplate>

        <DataTemplate x:Key="TopLevelTabHeaderTemplate">
            <TextBlock Text="{Binding Path=Name}"/>
        </DataTemplate>
        <DataTemplate x:Key="TopLevelTabContentTemplate">
            <TabControl ItemsSource="{Binding Path=Bars}"
                        ItemTemplate="{StaticResource NestedTabHeaderTemplate}" 
                        ContentTemplate="{StaticResource NestedTabContentTemplate}"
                        />
        </DataTemplate>
    </Grid.Resources>

    <TabControl ItemSource="{Binding correct binding for my control's collection of Foos}"
                ItemTemplate="{StaticResource TopLevelTabHeaderTemplate}" 
                ContentTemplate="{StaticResource TopLevelTabContentTemplate}"
                            x:Name="tabControl"
                />
</Grid>

要放入的话,有一个标签控制,每个foo的标签。每个foo是一个标签控制,每个酒吧它包含在它自己的标签。每个条包含的其Quxes的列表框。

To put it into words, there's a tab control, with a tab for each Foo. Each Foo is a tab control, with each Bar it contains in it's own tab. Each Bar contain's a listbox of its Quxes.

 ______ ______ ______  
| Foo1 | Foo2 | Foo3 |  
|______ ______       |  
| Bar1 | Bar2 |______|  
| | qux1            ||  
| | qux2            ||  
| | qux3            ||  
---------------------- 

我也有,我想用来筛选这个击穿一个TextBox。 当我在文本框中键入,我想过滤quxes所以那些不包含文本将不可见的。理想酒吧标签也将自己有没有明显的quxes隐藏,标签时隐时现,他们没有明显的酒吧取值

I also have a TextBox that I'd like to use to filter this breakdown. When I type in the text box, I'd like to filter the quxes so those not containing the text wouldn't be visible. Ideally Bar tabs would also be hidden if they have no visible quxes, and Foo tabs hidden when they have no visible Bars

我已经考虑两种方法:

在我的文本框的TextChanged事件,我遍历我Foo的要求相应的(静态)的TabControl的CollectionViewSource:

On my text box's TextChanged event, I loop through my Foo's asking for the corresponding (static) TabControl's CollectionViewSource:

foreach(Foo foo in tabControl.Items)
{
    var tabItem = tabControl.ItemContainerGenerator.ContainerFromItem(foo);    // This is always of type TabItem
    // How do I get the TabControl that will belong to each of Foo's Bar's?
}

方法2,申报ListView的的ItemSource到CollectionViewSource

我想通过XAML中设置过滤器,通过改变这一行:

Approach 2, declare the ListView's ItemSource to a CollectionViewSource

I tried setting the Filter via xaml, by changing this line:

<ListBox ItemsSource="{Binding Path=Quxes}" DisplayMemberPath="Name">

此,

<CollectionViewSource x:Key="MyCVS" Source="?????" Filter="MyCVS_Filter" />
...
<ListBox ItemsSource="{Binding Source={StaticResource MyCVS}}" DisplayMemberPath="Name">

我已经尝试了一些事情,我有?????但我不能正确地绑定到ListBox的DataContext的和适当的Quxes成员。没事我尝试显示结果在quxes,而我得到的控制台上没有错误。即使我能得到这种方法工作,我不知道什么时候在搜索框中的文本改变了我将如何再触发此过滤器。

I've tried a number of things where I have "?????" but I cannot correctly bind to the ListBox's datacontext and appropriate Quxes member. Nothing I try results in the quxes being displayed, and I get no errors on the console. Even If I could get this approach to work, I'm not sure how I would re-trigger this filter when the text in the search box changed.

任何意见或方向将是AP preciated。

Any advice or direction would be appreciated.

推荐答案

修改

最后我找到了符合你的要求的工作。

Finally I've got it working with your requirements.

这里是链接到更新的项目

(由卢克编辑)

这是(优秀)解决方案,我结束了去,所以我要提取的重要组成部分,实际上使他们在这里的帖子的一部分:

This is the (excellent) solution I ended up going with, so I'm going to extract the important parts, and actually make them part of the post here:

关键XAML部分结束了寻找这样的:

The key xaml portion ends up looking like this:

<CollectionViewSource x:Key="FooCVS" x:Name="_fooCVS" Source="{Binding Foos, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type WpfApplication1:MainWindow}}}" Filter="_fooCVS_Filter"/>
<CollectionViewSource x:Key="BarCVS" x:Name="_barCVS" Source="{Binding Bars, Source={StaticResource FooCVS}}" Filter="_barCVS_Filter"/>
<CollectionViewSource x:Key="QuxCVS" x:Name="_quxCVS" Source="{Binding Quxs, Source={StaticResource BarCVS}}"  Filter="_quxCVS_Filter"/>

我设置了​​相应的控制,以这些意见作为对照的的ItemSource 各一个。神奇的是在绑定的每个CVS的。每个CVS得到了出现在该控件/模板控件的数据范围内,因此您可以使用绑定对象的集合的真实姓名。我不知道我理解为什么绑定源绑定到本身(CVS)的作品的来源,但它确实如此美妙。

I set the respective control to each one of these views as the control's ItemSource. The magic is in the binding of each CVS. Each CVS gets the data context for the control/templated control in which appears, so you can use the the real name of the bound object's collection. I'm not sure I understand why binding the source of that source binding to itself (the CVS) works, but it does so beautifully.

在code为滤波文本框则变成是这样的:

The code for the filter TextBox then becomes something like:

private void filterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    var cvs = TryFindResource("FooCVS") as CollectionViewSource;
    if (cvs != null)
    {
        if (cvs.View != null)
            cvs.View.Refresh();
    }
    cvs = TryFindResource("QuxCVS") as CollectionViewSource;
    if (cvs != null)
    {
        if (cvs.View != null)
            cvs.View.Refresh();
    }
    cvs = TryFindResource("BarCVS") as CollectionViewSource;
    if (cvs != null)
    {
        if (cvs.View != null)
            cvs.View.Refresh();
    }
}

最佳解决方案,因为它不需要任何基础对象或层次。

Excellent solution as it requires no changing of the underlying objects or hierarchy.

这篇关于过滤分层对象嵌套XAML数据显示模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆