小编典典

这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection

all

我有一个 DataGrid,它通过异步方法从 ViewModel 填充数据。我的 DataGrid 是:

<DataGrid ItemsSource="{Binding MatchObsCollection}"  x:Name="dataGridParent" 
                      Style="{StaticResource EfesDataGridStyle}" 
                      HorizontalGridLinesBrush="#DADADA" VerticalGridLinesBrush="#DADADA" Cursor="Hand" AutoGenerateColumns="False" 
                      RowDetailsVisibilityMode="Visible"  >

我正在使用http://www.amazedsaint.com/2010/10/asynchronous-delegate-command-for-
your.html在我的视图模型中实现异步方式。

这是我的视图模型代码:

public class MainWindowViewModel:WorkspaceViewModel,INotifyCollectionChanged
    {

        MatchBLL matchBLL = new MatchBLL();
        EfesBetServiceReference.EfesBetClient proxy = new EfesBetClient();

        public ICommand DoSomethingCommand { get; set; }
        public MainWindowViewModel()
        {
            DoSomethingCommand = new AsyncDelegateCommand(
                () => Load(), null, null,
                (ex) => Debug.WriteLine(ex.Message));           
            _matchObsCollection = new ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC>();

        }

        List<EfesBet.DataContract.GetMatchDetailsDC> matchList;
        ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC> _matchObsCollection;

        public ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC> MatchObsCollection
        {
            get { return _matchObsCollection; }
            set
            {
                _matchObsCollection = value;
                OnPropertyChanged("MatchObsCollection");
            }
        }        
        //
        public void Load()
        {            
            matchList = new List<GetMatchDetailsDC>();
            matchList = proxy.GetMatch().ToList();

            foreach (EfesBet.DataContract.GetMatchDetailsDC match in matchList)
            {
                _matchObsCollection.Add(match);
            }

        }

正如您在 ViewModel 中的 Load() 方法中看到的,首先我从服务中获取 matchList(这是 DataContract 类的列表)。然后通过
foreach 循环,我将 matchList 项插入到我的 _matchObsCollection(这是一个 ObservableCollection
DataContract 类))。现在我收到上述错误(如标题中所示)“这种类型的 CollectionView 不支持从不同于 Dispatcher
线程的线程更改其 SourceCollection” 在此处输入图像描述

谁能建议我任何解决方案。此外,如果可能的话,我想知道如何在 View 中绑定我的 DataGrid,如果有更好的方法,也可以异步刷新它。


阅读 67

收藏
2022-08-24

共1个答案

小编典典

由于您的 ObservableCollection 是在 UI 线程上创建的,因此您只能从 UI
线程修改它,而不能从其他线程修改它。这称为线程亲和性

如果您需要从不同的线程更新在 UI 线程上创建的对象,只需put the delegate on UI Dispatcher将其委派给 UI
线程即可。这将起作用 -

    public void Load()
    {
        matchList = new List<GetMatchDetailsDC>();
        matchList = proxy.GetMatch().ToList();

        foreach (EfesBet.DataContract.GetMatchDetailsDC match in matchList)
        {
            App.Current.Dispatcher.Invoke((Action)delegate // <--- HERE
            {
                _matchObsCollection.Add(match);
            });
        }
    }
2022-08-24