这种类型的CollectionView不支持从与调度程序线程不同的线程更改其SourceCollection

17 浏览
0 Comments

这种类型的CollectionView不支持从与调度程序线程不同的线程更改其SourceCollection

这个问题已经在此处有答案:

如何通过工作线程更新ObservableCollection?

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


我正在使用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();                
        }       
        List matchList;
        ObservableCollection _matchObsCollection;
        public ObservableCollection MatchObsCollection
        {
            get { return _matchObsCollection; }
            set
            {
                _matchObsCollection = value;
                OnPropertyChanged("MatchObsCollection");
            }
        }        
        //
        public void Load()
        {            
            matchList = new List();
            matchList = proxy.GetMatch().ToList();
            foreach (EfesBet.DataContract.GetMatchDetailsDC match in matchList)
            {
                _matchObsCollection.Add(match);
            }
        }

正如您在我的ViewModel的Load()方法中所看到的那样,我首先从服务中获取matchList(它是DataContract类的列表)。然后,通过foreach循环,我将我的matchList项插入到我的_matchObsCollection(它是DataContract类的ObservableCollection)中。现在,在这里,我正在遇到上面显示的错误(如标题所示)“此CollectionView类型不支持来自与Dispatcher线程不同的线程的SourceCollection更改”。

\"enter

有人可以给我建议吗?此外,如果有可能,我想知道如何在View中绑定我的DataGrid并异步刷新它(如果有更好的方法)。

admin 更改状态以发布 2023年5月24日
0
0 Comments

如果我没有记错,在WPF 4.5中,您应该可以毫无问题地完成这项工作。

现在,要解决这个问题,您应该使用同步上下文。在启动线程之前,您必须在UI线程中存储同步上下文。

var uiContext = SynchronizationContext.Current;

然后在您的线程中使用它:

uiContext.Send(x => _matchObsCollection.Add(match), null);

参考这个教程:http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I

0
0 Comments

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

如果你需要从不同的线程更新在UI线程上创建的对象,只需将委托放在UI Dispatcher上,它将委托给UI线程完成工作。这将起作用 –

    public void Load()
    {
        matchList = new List();
        matchList = proxy.GetMatch().ToList();
        foreach (EfesBet.DataContract.GetMatchDetailsDC match in matchList)
        {
            App.Current.Dispatcher.Invoke((Action)delegate // <--- HERE
            {
                _matchObsCollection.Add(match);
            });
        }
    }

0