WPF 数据绑定是否将更改编组到 UI 线程? [英] Does WPF databinding marshall changes to the UI Thread?

查看:14
本文介绍了WPF 数据绑定是否将更改编组到 UI 线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚注意到,从后台工作线程更改我的 ViewModel (MVVM) 中的绑定属性时,我没有收到任何异常,并且视图已正确更新.这是否意味着我可以安全地依赖 wpf 数据绑定将 ViewModel 中的所有更改编组到 UI 线程?我想我在某个地方读到过,应该确保(在 ViewModel 中)在 UI 线程上触发 INotifyPropertyChanged.PropertyChanged.这是否在 3.5 或其他版本中发生了变化?

I just noticed that when changing bound properties in my ViewModel (MVVM) from a background worker thread I do not get any exceptions and the view is updated correctly. Does this mean I can safely rely on wpf databinding marshalling all changes in the ViewModel to the UI Thread? I think I have read somewhere that one should make sure (in the ViewModel) that INotifyPropertyChanged.PropertyChanged is fired on the UI thread. Has this changed in 3.5 or something?

推荐答案

是的标量,不是集合.对于集合,您需要一个专门的集合来为您编组,或者您自己通过 Dispatcher 手动编组到 UI 线程.

Yes for scalars, no for collections. For collections, you'll need a specialized collection that marshals for you, or manually marshal to the UI thread yourself via the Dispatcher.

您可能已经读过 INotifyCollectionChanged.CollectionChanged 必须在 UI 线程上触发,因为 INotifyPropertyChanged.PropertyChanged 根本不是这样.下面是一个非常简单的示例,它证明 WPF 为您编组了属性更改.

You may have read that INotifyCollectionChanged.CollectionChanged must fire on the UI thread, because it's simply not true of INotifyPropertyChanged.PropertyChanged. Below is a very simple example that proves WPF marshals property changes for you.

Window1.xaml.cs:

using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        private CustomerViewModel _customerViewModel;

        public Window1()
        {
            InitializeComponent();
            _customerViewModel = new CustomerViewModel();
            DataContext = _customerViewModel;

            var thread = new Thread((ThreadStart)delegate
            {
                while (true)
                {
                    Thread.Sleep(2000);
                    //look ma - no marshalling!
                    _customerViewModel.Name += "Appended";
                    _customerViewModel.Address.Line1 += "Appended";
                }
            });

            thread.Start();
        }
    }

    public abstract class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class CustomerViewModel : ViewModel
    {
        private string _name;
        private AddressViewModel _address = new AddressViewModel();

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    OnPropertyChanged("Name");
                }
            }
        }

        public AddressViewModel Address
        {
            get { return _address; }
        }
    }

    public class AddressViewModel : ViewModel
    {
        private string _line1;

        public string Line1
        {
            get { return _line1; }
            set
            {
                if (_line1 != value)
                {
                    _line1 = value;
                    OnPropertyChanged("Line1");
                }
            }
        }
    }
}

Window1.xaml:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <TextBox Text="{Binding Name}"/>
        <TextBox Text="{Binding Address.Line1}"/>
    </StackPanel>
</Window>

这篇关于WPF 数据绑定是否将更改编组到 UI 线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆