WPF CollectionViewSource.Filter Performance v.DataTrigger

时间:2011-08-25 15:52:46

标签: wpf datatrigger collectionviewsource

实体框架提供具有名为ChangeTracker.State的属性的可跟踪实体。使用此功能,我们可以识别实体是否已删除。

在我们的列表中,我们不希望显示已删除的实体。

哪个更快?

方法1:使用CollectionViewSource.Filter测试并删除记录

<CollectionViewSource Filter="ViewSource_Filter" />

private void ViewSource_Filter(object sender, FilterEventArgs e)
{
    var _Item = e.Item as ITrackableEntity;
    e.Accepted = _Item.ChangeTracker.State != ObjectState.Deleted;
}

方法2:将DataTrigger添加到ItemTemplate.DataTemplate以测试和隐藏项目

<DataTemplate.Resources>
    <Style TargetType="{x:Type DockPanel}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ChangeTracker.State}">
                <DataTrigger.Value>
                    <entities:ObjectState>Deleted</entities:ObjectState>
                </DataTrigger.Value>
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataTemplate.Resources>

感谢。

3 个答案:

答案 0 :(得分:2)

假设有一个ItemsControl涉及此问题,我个人喜欢基于collectionview的过滤器。

...的原因

  1. 它的过滤权在ViewModel手中。因此,每当它想要刷新集合视图时,它将再次重新过滤。

  2. 如果仅在UI的整个生命周期中填充ChangeTracker.State属性并且未更新,则集合视图将仅在渲染时过滤一次。另一方面,DataTriggers将等待ChangeTracker.State可能/可能不会发生的任何更改。

  3. 交替项目应用此CollectionView的ItemsControl的行样式将不会对数据触发器产生正确的效果,因为它只会隐藏项目而不会调整备用行样式,但collectionview将排除项目预先自己。即如果备用行需要是灰色背景,那么如果使用DataTrigger,则可能会发生两个相邻的行为灰色。

  4. DataTriggers仅对非虚拟化项目生效,因此Scrollbar启发式可能会被搞砸如果滚动视图仅显示10个项目可见且源中有90个项目但50个项目处于Deleted状态,则除非我们滚动到它们,否则它们的数据触发器将不会生效。因此在此期间,滚动条将重新计算并闪烁以调整其实际滚动值。所以它可能像我们有100个项目适用于滚动,而实际上它只需要50个项目滚动到。

  5. CollectionView提供了50个项目来自动滚动视图。

    因此,就性能而言,DataTrigger会更加快速,因为只有当项目被去虚拟化时才会应用,即滚动视图。但它可能会引发上述问题。

    如果有帮助,请告诉我。

答案 1 :(得分:0)

但Loaded事件可能包含您需要的信息。从MSDN:在最终渲染之前引发Loaded事件,但在布局系统计算了所有必要的渲染值之后。 Loaded需要包含元素的逻辑树是完整的,并连接到提供HWND和渲染表面的表示源。我对此的解释是过滤器和触发器已被处理但我并不积极。卸载不是最终的数字,但我认为你会比较苹果和苹果。但仍然苹果可能不是正确的比较。如果调试器走了XAML会很好。由于调试器没有走XAML,我认为你不能直接测量触发器。最好的希望是测量页面。创建一个只包含困难过滤器的页面。

    public MainWindow()
    {
        Debug.WriteLine(DateTime.Now.ToLongTimeString());
        InitializeComponent();
        Debug.WriteLine(DateTime.Now.ToLongTimeString());
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine(DateTime.Now.ToLongTimeString());

Debug与直接执行不同,所以我将这些绑定到TextBlocks 3次。我还会比较XAML中定义的过滤器。我的直觉是两者都会如此之快以至于很难知道差异,但我猜测过滤器会更快。

答案 2 :(得分:0)

方法1 是正确答案。