I have an ObservableCollection bound to a WPFToolkit DataGrid in an MVVM pattern. Every 30 seconds I have a background thread that is querying a service for some data. When it returns, it marshals it to the UI thread and updates the ObservableCollection by first calling Clear() on the collection and then calling Add() for each item. When this happens, the data is updated properly to the screen, however, the datagrid flickers. How can I prevent this from happening?
views:
118answers:
2I created a simple but maximum powerfull solution for your problem:
public class MyCollection<T> : ObservableCollection<T>
{
private bool _isInEditMode = false;
public void BeginEdit()
{
_isInEditMode = true;
}
public void CommitEdit()
{
_isInEditMode = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (_isInEditMode == false)
{
base.OnCollectionChanged(e);
}
}
}
The my collection class prevents collection changed events while you are in edit mode. Start "BeginEdit" before clearing the items. Then add your new items. When you are finished, use "CommitEdit" and the view will refresh only once.
If have tested it with a simple listbox, where i add 1.000.000 string items. Try this out. Its funny :)
private void Button_Click(object sender, RoutedEventArgs e)
{
MyCollection<string> list = testBox.ItemsSource as MyCollection<string>;
//list.BeginEdit();
for (int i = 0; i < 1000000; i++)
{
list.Add("test " + i);
}
list.CommitEdit();
}
Remove the // from list.BeginEdit() and see the difference. Its about 15 seconds agains < 1 second.
Greetings,
Jan
It appears you're simply replacing all of your data if you're clearing then adding each item one at a time. Instead of re-using your ObservableCollection, can you simply set your data grid's itemssource to a new ObservableCollection with your new items?