【问题标题】:MVVM Dynamic DataGrid Sorting FilteringMVVM 动态 DataGrid 排序过滤
【发布时间】:2013-04-18 12:19:40
【问题描述】:

我有一个DataGrid,它通过Thread 每隔几秒更新一次数据。 DataGrid 需要提供 Column Header 排序、分组和过滤。

我目前有一个DataGrid 绑定到一个ICollectionView 并且ICollectionView 的源是一个ObservableCollection。从我在其他线程上阅读的内容来看,这似乎是实现此目的的好方法。

排序“有效”,但在更新ObservableCollection 后更新ICollectionView.Source 时它会丢失。我尝试在更新前保存SortDescriptions,并在更新完成后将其重新添加到ICollectionView。但结果是一样的。

有人可以指出我缺少什么吗?

编辑这里有一些代码...

查看 (XAML)

<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}>

视图模型

public ICollectionView CollectionView
{
    get
    {
        collectionViewSource.Source = dataColl;
        if (SortDescriptions != null)
        {
            foreach (SortDescription sd in SortDescriptions)
            {
                collectionViewSource.View.SortDescriptions.Add(sd);
            }
        }
        collectionViewSource.View.Refresh();
        return collectionViewSource.View;
    }
}

public ObservableCollection<SomeObject> DataColl
{
    get { return dataColl; }
    private set 
    {
        this.dataColl= value;
        OnPropertyChanged("CollectionView");
    }
}

以下是每隔几秒更新一次数据的方法……

private void UpdateData()
{
    while (true)
    {
        System.Threading.Thread.Sleep(mDataRefreshRate);

        // SortDescriptions is a Property of the ViewModel class.
        SortDescriptions = collectionViewSource.View.SortDescriptions;

        ObservableCollection<SomeObject> wDataColl
           = new ObservableCollection<SomeObject>();

        //... Irrelevant code that puts the data in wDataColl ...

        DataColl= wDataColl;
    }
}

【问题讨论】:

  • 可以添加一些你试过的源代码吗?

标签: c# wpf mvvm datagrid filtering


【解决方案1】:
[YourObservableCollection].ViewHandler.View.Filter
                    += new FilterEventHandler(myFilterHandler);

private void myFilterHandler(object sender, FilterEventArgs e)
{
}

可用于直接添加您的过滤器处理程序,您可以使用SortDescriptions 执行相同的操作来添加/删除

[YourObservableCollection].ViewHandler.View.SortDescriptions.Add(mySortDescription);

如果您正在分配排序和过滤,最好创建自己的类来封装 CollectionViewSource 并实现添加和删除 SortDescriptions 和过滤等

当你说:

排序“有效”,但当 ICollectionView.Source 获取时它会丢失 在 ObservableCollection 更新后更新

更新是什么意思?你的意思是你正在改变源?而不是从集合中添加/删除项目?

根据您添加的 XAML 示例进行编辑:

<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}>

您正在将 itemsource 绑定到 CollectionViewSource,您应该将数据上下文绑定到它:

例子:

<Page.Resources>
    <CollectionViewSource x:Key="myViewSource"
          Source="{Binding CollectionView, Source={StaticResource ViewModel}}"
    />
</Page.Resources>

在页面中:

<Grid DataContext="{StaticResource myViewSource}">

        <DataGrid x:Name="myGrid"  ItemsSource="{Binding}"...

或者类似的东西

再次编辑没有看到代码向下滚动:p

ObservableCollection<SomeObject> wDataColl= new ObservableCollection<SomeObject>();

每次收集时都会创建新实例,这是主要问题

还有:

public ICollectionView CollectionView
{
    get
    {
        collectionViewSource.Source = dataColl;
        if (SortDescriptions != null)
        {
            foreach (SortDescription sd in SortDescriptions)
            {
                collectionViewSource.View.SortDescriptions.Add(sd);
            }
        }
        collectionViewSource.View.Refresh();
        return collectionViewSource.View;
    }
}

在这里你返回集合你设置Source和添加SortDescriptions并且每次刷新视图,你只需要设置一次这些值

如果你添加/删除SortDescriptions,你只会在视图上调用刷新

我认为你应该掌握CollectionViewSource的基础知识

【讨论】:

  • >更新是什么意思?你的意思是你正在改变源?而不是从集合中添加/删除项目?
    没错!显然,除非我将 ICollectionView.Source 属性重新影响到 observablecollection,否则数据不会更新。
  • 这样做和我这样做有什么不同?我遵循了 Niclas 的建议,到目前为止效果很好......
  • >您每次收集时都会创建新实例,这是主要问题现在已更改,我使用 ObservableCollection.Add now
  • DeferRefresh 可能有助于提高性能。它是我使用 DataGrid 后的新朋友。
【解决方案2】:

问题是每次添加新数据时都会换掉整个 ObservableCollection。

    ObservableCollection<SomeObject> wDataColl= new ObservableCollection<SomeObject>();

    ... Unrelevant code that puts the data in wDataColl ...

    DataColl= wDataColl;

确保改为使用“添加到现有集合”(如果有必要,可能先使用 Clear() 之后)...如果之后仍有问题,请发表评论,我会尽力提供帮助。

另外,尽量避免使用Refresh(),因为它会重建整个视图并且不必要地昂贵。如果您进行排序、添加、删除等操作,则不需要使用 Refresh() 的正确方法。

【讨论】:

  • 谢谢 Niclas。它以这种方式工作,但似乎破坏了过滤。我确实像这样设置了一个回调句柄 ICollectionView 过滤器。 myCollectionView.Filter += filterCallback;什么时候应该触发我的回调?我应该说...当我对列进行排序时,我的回调会被调用...
  • 您没有在代码中进行任何过滤。 SortDescriptions 用于对集合进行排序,过滤器用于删除您想要/不想显示的不需要的项目。
  • @MarkHomer 我没有将代码直接放在我的示例中,而是放在我之前的评论中。我确实设置了 myCollectionView.Filter += filterCallback;在我的 ViewModel 构造函数中。但是,它什么时候被调用?我必须触发刷新吗?
  • @Niclas 抱歉,我把这条评论发给了 ncourcy,我应该把 at, sorry new 在这个网站上,因为他在问过滤器事件处理程序。
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 2020-10-13
  • 2020-06-07
  • 1970-01-01
  • 2021-09-03
  • 2018-12-08
  • 2017-09-02
  • 2020-08-25
相关资源
最近更新 更多