WPF CollectionViewSource.过滤器性能v.数据触发器



实体框架提供了可追踪的实体,它们有一个名为ChangeTracker.State的属性。使用它,我们可以识别一个实体是否被删除。

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

哪个更快?

方法1:使用CollectionViewSource。筛选以测试并删除记录

<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:向ItemTemplate中添加DataTrigger。用于测试和隐藏项目的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>

谢谢。

假设这个问题涉及ItemsControl,我个人喜欢基于集合视图的过滤器。

原因……

  1. 它的过滤是在ViewModel的手中。所以当它想刷新集合视图时,它会重新过滤。

  2. 如果ChangeTracker.State属性在UI的整个生命周期中只被填充而不更新,那么集合视图将只在渲染时过滤一次。另一方面,数据触发器将等待ChangeTracker.State的任何更改,这些更改可能会发生,也可能不会发生。

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

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

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

因此,就性能而言,DataTrigger将会更快,因为它只会在项目被去虚拟化时应用,即在滚动视图中应用。但它可能会带来上述问题。

如果有帮助请告诉我

但是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());

调试与直接执行不一样,所以我会将这3次绑定到TextBlocks。我还将与XAML中定义的过滤器进行比较。我的直觉是,两者都将是如此之快,很难知道区别,但我猜过滤器更快。

方法1为正确答案

最新更新