WPF跨线程修改UI数据源解决办法之Dispatcher

View层两个控件:ListBox展示数据,Add按钮点击以后添加一行数据:


<ListBox Margin="50" ItemsSource="{Binding TestCollection}"></ListBox>
<Button x:Name="button" Content="ADD" Command="{Binding AddCommand}" HorizontalAlignment="Left" Margin="625,393,0,0" VerticalAlignment="Top" Width="75"/>

ViewModel层:

    public class MainFormVM
    {
        public ObservableCollection<string> TestCollection { get; set; } = new ObservableCollection<string>() { "~", "~" };

        public ICommand AddCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    AddData();
                });
            }
        }

        private void AddData()
        {
            TestCollection.Add("~");
        }
    }

以上代码执行之后没有任何问题但是当我们用另一个线程执行AddData方法时:

        public ICommand AddCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    Thread t = new Thread(AddData);
                    t.Start();
                });
            }
        }

会出现异常:System.NotSupportedException:“该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。

解决办法:

 public class MainFormVM
    {
        public ObservableCollection<string> TestCollection { get; set; } = new ObservableCollection<string>() { "~", "~" };

        private Dispatcher m_Dispatcher = Dispatcher.FromThread(Thread.CurrentThread);

        public ICommand AddCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    Thread t = new Thread(AddData);
                    t.Start();
                });
            }
        }

        private void AddData()
        {
            m_Dispatcher.Invoke(() =>
            {
                TestCollection.Add("~");
            });
        }
    }

m_Dispatcher为UI线程对应的Dispatcher,当线程t执行AddData方法时,Invoke方法会把其参数方法封送到UI线程中去执行。

猜你喜欢

转载自blog.csdn.net/weixin_41583998/article/details/88393118