时间:2010-07-23 18:26:47

标签: c# xaml binding filtering datatemplate

3 个答案:

答案 0 :(得分:3)

修改

最后,我已经满足了你的要求。

Here is the link to the updated project


(由卢克编辑)

这是我最终选择的(优秀)解决方案,因此我将提取重要部分,并实际上将它们作为帖子的一部分:

关键的xaml部分最终看起来像这样:

<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)的工作原理,但它确实如此美妙。

过滤器TextBox的代码就变成了:

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();
    }
}

优秀的解决方案,因为它不需要更改底层对象或层次结构。

答案 1 :(得分:2)

答案 2 :(得分:0)

我今天的工作遇到了类似的问题,并提出了以下解决方案:

  1. 直接或通过适配器模式为所有元素添加Visibility属性。

        Visibility Visibility
        {
            get { return visibility; }
            set { visibility = value; PropertyChanged("Visibility"); }
        }
    
  2. 将控件的Vis Visibility属性绑定到step1中相应的Visibility属性。

  3. 通过扩展方法或内部对数据实施简单过滤。

    void Filter(Func<Foo, bool> filterFunc)
    {
        foreach (var item in foos)
        {
            if (!filterFunc(item))
                item.Visibility = Visibility.Collapsed;
            else
                item.Visibility = Visibility.Visible;
        }
    }
    
  4. 在TextBox的TextChanged事件上添加简单的过滤器调用。

    过滤器(n =&gt; n.Name.ToLower()。包含(textBox.Text));

  5. 或者对容器控件更高级:

    Filter(c => c.Items.Any(i => i.Visibility == Visibility.Visible));