Upgrading to .NET 4.5: An ItemsControl is inconsistent with its items source

后端 未结 4 1761
心在旅途
心在旅途 2020-12-08 07:24

I\'m building an application, which uses many ItemControls(datagrids and listviews). In order to easily update these lists from background threads I used this extension to O

4条回答
  •  天命终不由人
    2020-12-08 07:59

    WPF 4.5 provides some new functionality to access collections on non-UI Threads.

    It WPF enables you to access and modify data collections on threads other than the one that created the collection. This enables you to use a background thread to receive data from an external source, such as a database, and display the data on the UI thread. By using another thread to modify the collection, your user interface remains responsive to user interaction.

    This can be done by using the static method EnableCollectionSynchronization on the BindingOperations class.

    If you have a lot of data to collect or modify, you might want to use a background thread to collect and modify the data so that the user interface will remain reactive to input. To enable multiple threads to access a collection, call the EnableCollectionSynchronization method. When you call this overload of the EnableCollectionSynchronization(IEnumerable, Object) method, the system locks the collection when you access it. To specify a callback to lock the collection yourself, call the EnableCollectionSynchronization(IEnumerable, Object, CollectionSynchronizationCallback) overload.

    The usage is as follows. Create an object that is used as a lock for the synchronization of the collection. Then call the EnableCollectionSynchronization method of the BindingsOperations and pass to it the collection you want to synchronize and the object that is used for locking.

    I have updated your code and added the details. Also i changed the collection to the normal ObservableCollection to avoid conflicts.

    public partial class MainWindow : Window{
      public ObservableCollection Items { get; private set; }
    
      //lock object for synchronization;
      private static object _syncLock = new object();
    
      public MainWindow()
      {
        InitializeComponent();
        Items = new ObservableCollection();
    
        //Enable the cross acces to this collection elsewhere
        BindingOperations.EnableCollectionSynchronization(Items, _syncLock);
    
        DataContext = this;
        Loaded += MainWindow_Loaded;
      }
    
      void MainWindow_Loaded(object sender, RoutedEventArgs e)
      {
            Task.Factory.StartNew(() =>
            {
                foreach (var item in Enumerable.Range(1, 500))
                {
                    lock(_syncLock) {
                      Items.Add(item);
                    }
                }
            });                
      }
    }
    

    See also: http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux

提交回复
热议问题