ncourcy84
ncourcy84

Reputation: 101

MVVM Dynamic DataGrid Sorting Filtering

I have a DataGrid that gets its data updated every few seconds via a Thread. The DataGrid needs to offer Column Header sorting, grouping and filtering.

I currently have a DataGrid bound to a ICollectionView and the source of the ICollectionView is an ObservableCollection. Which seems to be the good way to do it from what I read on other threads.

The sort-ing "works" but it gets lost when the ICollectionView.Source gets updated following an update of the ObservableCollection. I have tried saving the SortDescriptions before the update and re-add it to the ICollectionView after the update is done. But it's the same result.

May someone point me to what I'm missing?

Edit Here's some code...

View (XAML)

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

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");
    }
}

Following is the method that updates the data every few seconds...

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;
    }
}

Upvotes: 2

Views: 7102

Answers (2)

Mark Homer
Mark Homer

Reputation: 1035

[YourObservableCollection].ViewHandler.View.Filter
                    += new FilterEventHandler(myFilterHandler);

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

Can be used to directly add your filter handler and you can do the same with SortDescriptions to Add/Remove

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

If you are doing allot of sorting and filtering best to create own class encapsulating a CollectionViewSource and implement adding and removing SortDescriptions and Filtering etc

When you say:

The sort "works" but it gets lost when the ICollectionView.Source gets updated following an update of the ObservableCollection

What do you mean by update? you mean you are changing the Source? Rather than adding/removing items from the collection?

EDIT based on your XAML example you added:

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

You are binding itemsource to the CollectionViewSource where you should bind the datacontext to it:

Example:

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

In page:

<Grid DataContext="{StaticResource myViewSource}">

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

Or something along those lines

EDIT again didnt see code scroll down :p

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

You create new instance every time of collection lol this is main problem

Also:

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;
    }
}

Here where you return collection you are setting the Source and adding the SortDescriptions and also refreshing the view every time, you only need set these values once

You would only call refresh on the View if you add/remove SortDescriptions

I think you should get to grips with basics of CollectionViewSource

Upvotes: 2

Niclas
Niclas

Reputation: 1230

The problem is that you swap out the entire ObservableCollection every time you add new data.

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

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

    DataColl= wDataColl;

Make sure to use Add to the existing collection instead (perhaps after using Clear() first if that is necessary)... If you still have problems after that please comment and i will try to help.

Also, try to avoid using the Refresh() as it rebuilds the entire view and is unnecessarily expensive. If you do sorting, adding, removing etc. the correct way use of Refresh() isn't needed.

Upvotes: 0

Related Questions