MVVM动态DataGrid排序过滤

时间:2013-04-24 19:31:23

标签: c# wpf mvvm datagrid filtering

我有DataGrid通过Thread每隔几秒更新一次数据。 DataGrid需要提供列标题排序,分组和过滤。

我目前有一个DataGrid绑定到ICollectionView,而ICollectionView的来源是ObservableCollection。这似乎是我在其他线程上阅读的好方法。

排序“有效”但在更新ICollectionView.SourceObservableCollection更新时会丢失。我尝试在更新之前保存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;
    }
}

2 个答案:

答案 0 :(得分:2)

[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,您应该将datacontext绑定到它:

示例:

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

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

此外:

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

的基础知识

答案 1 :(得分:0)

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

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

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

    DataColl= wDataColl;

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

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