CollectionViewSource,如何过​​滤数据?

spi*_*man 5 c# binding filtering collectionviewsource

我正在将ComboBox绑定到实体,但我希望过滤数据.

到目前为止,我尝试了两种方法:

  • "简单"一:通过LINQ to Entities将过滤器直接应用于ObjectSet
  • 设置过滤事件处理程序,如 msdn所述

我对第一种方法感到满意,首先是因为生成到数据库的查询包含WHERE子句,所以不是所有的数据都必须从远程数据库中检索....

但是,#2方法更灵活,如果在运行时我想更改应用的过滤...我已经按照msdn上的示例,但我得到一个例外,为什么?

所以,我的问题是:
1.哪种方法更好
2.为什么我得到例外?

这是我的代码:

 private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        //Do not load your data at design time.
        if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
        {
            //Load your data here and assign the result to the CollectionViewSource.
            System.Windows.Data.CollectionViewSource myCollectionViewSource =
                (System.Windows.Data.CollectionViewSource)
                this.Resources["tSCHEDEViewSource"];

            // If I use this I get the data filtered on startup, but is it the right mode?
            //myCollectionViewSource.Source = _context.TSCHEDE.Where(s => s.KLINEA == kLinea && s.FCANC == "T").OrderBy(s => s.DSCHEDA).OrderByDescending(s => s.DSTORICO);

            // Instead If I apply my custom filtering logic
            myCollectionViewSource.Filter += new FilterEventHandler(filterSource);

            myCollectionViewSource.Source = _context.TSCHEDE; // ... Here i get an exception: 
            // 'System.Windows.Data.BindingListCollectionView' view does not support filtering. ???
        }
    }


    private void filterSource(object sender, FilterEventArgs e)
    {
        TSCHEDE scheda = e.Item as TSCHEDE;
        if (scheda != null)
        {
            if (scheda.KLINEA == 990)
            {
                e.Accepted = true;
            }
            else
            {
                e.Accepted = false;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑:我尝试在View上实现Filter属性,而不是设置EventHandler:

myCollectionView = (BindingListCollectionView)myCollectionViewSource.View;
myCollectionView.Filter = new Predicate<object>(Contains);

public bool Contains(object de)
    {
        TSCHEDE scheda = de as TSCHEDE;
        return (scheda.KLINEA == 990);
    }
Run Code Online (Sandbox Code Playgroud)

现在我得到了不那么有用的例外:

System.NotSupportedException:不支持指定的方法.在System.Windows.Data.CollectionView.set_Filter(Predicate`1值)

编辑

XAML代码:

<UserControl.Resources>
    <CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE, CreateList=True}"  >
    </CollectionViewSource>
    <DataTemplate x:Key="SchedaTemplate">
        <StackPanel Orientation="Horizontal" >
            <TextBlock Text="{Binding Path=KSCHEDA}" Width="60"></TextBlock>
            <TextBlock Text="{Binding Path=DArticolo}" Width="200"></TextBlock>
            <TextBlock Text=" - " Width="40"></TextBlock>
            <TextBlock Text="{Binding Path=DSTORICO}" Width="150"></TextBlock>
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>
<Grid Background="PapayaWhip" DataContext="{StaticResource tSCHEDEViewSource}" DataContextChanged="StartHere" Name="rootGrid">
    <ComboBox ItemTemplate="{StaticResource SchedaTemplate}" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="23,129,0,0" Name="tSCHEDEComboBox1" SelectedValuePath="KSCHEDA" VerticalAlignment="Top" Width="393">
        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
    </ComboBox>
</Grid>
Run Code Online (Sandbox Code Playgroud)

现在我认为问题出在XAML Binding中,而不是代码背后......

Mas*_*oke 8

检查一下

1)CollectionView过滤

过滤需要基于其发生过滤的委托(谓词).谓词根据返回的值true或false接收项目,它选择或取消选择元素.

this.Source.Filter = item => {
    ViewItem vitem = item as ViewItem;
    return vItem != null && vitem.Name.Contains("A");
};
Run Code Online (Sandbox Code Playgroud)

2)动态地处理数据

  • 出生于做复杂事情的程序员:-) (3认同)

spi*_*man 7

最后我找到了一个解决方案,在此问题中也发布 了expliticy来声明Collection的类型:

CollectionViewType = "的ListCollectionView"

所以在XAML中添加了Collection类型:

<CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE,  CreateList=True}" CollectionViewType="ListCollectionView">
    </CollectionViewSource>
Run Code Online (Sandbox Code Playgroud)

现在代码中的事件处理程序工作:

myCollectionViewSource.Filter += new FilterEventHandler(filterSource);
Run Code Online (Sandbox Code Playgroud)

唯一的遗憾是我不明白为什么,因为显然如此简单,我必须在XAML中"手动"强制它? 对我来说,这似乎是一个黑客,也很容易出错......

  • 你是不是只是在没有发表评论的情况下拒绝投票的人? (8认同)
  • @Yatin 真的没有那么奇怪。如果答案已经正确/有用,那么可能没有其他任何内容可以通过添加来提供好处。但是,如果答案不正确/有帮助,那么解释原因总是有好处的。无论哪种方式,尽管两年前我发表初步评论时曾多次投反对票,但现在这是公认的答案。 (3认同)