为什么在工作线程的视图模型中赋予字符串绑定属性不会抛出Argument Exception

时间:2015-06-11 15:54:25

标签: c# wpf multithreading mvvm

我最近经历了一个参数异常:必须在与DependencyObject相同的Thread上创建DependencySource。

我知道根本原因是试图将/ new对象绑定到不同的线程而不是第一个上,这会导致异常。

然而,它带来了另一个问题,即为什么它不会抛出异常,如果我实例化/ new string to binding属性来更新,例如,TextBlock的Text属性?

以下是不会抛出异常的代码。

==in xaml==
<TextBlock FontSize="20" Text="{Binding FirstName}"/>

==in view model==
private string firstName;
public string FirstName
{
    get { return firstName; }
    set 
    {
        firstName = value;
        RaisePropertyChnaged("FirstName");
    }
}

==in xaml.cs==
public MainWindow()
{
    InitializeComponent();
    this.DataContext = mViewModel = new MainViewModel();
    mViewModel.Color = new SolidColorBrush(Colors.Green);
    mViewModel.FirstName = "John";
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    //intent to udpate Textblock's Text on worker thread
    Task.Run(() => {                
        mViewModel.FirstName = "Andy";
    });
}

以下是代码将抛出ArgumentException

==in xaml==
<Rectangle Width="100" Height="100" Fill="{Binding Color}"/>

==in view model==
private SolidColorBrush color;
public SolidColorBrush Color
{
    get { return color; }
    set 
    { 
        color = value;
        RaisePropertyChnaged("Color");
    }
}

==in xaml.cs==
private void Button_Click(object sender, RoutedEventArgs e)
{
    //intent to udpate Rectangle's Fill property on worker thread
    Task.Run(() => {                
        Color = new SolidColorBrush(Colors.Red);
    });
}

1 个答案:

答案 0 :(得分:2)

从SolidBrushColor更改绑定属性Color的类型到Color,它不是从DispatcherObject继承的。它不会再抛出异常了。

还有一个类似的问题得到了很好的答案。

Must create DependencySource on same Thread as DependencyObject

AndrewS的回答让我大吃一惊。

以下是修改版

==in xaml==
<Rectangle Width="100" Height="100" Fill="{Binding Color, Converter={StaticResource MyConverter}}"/>

==in view model==
private Color color;
public Color Color
{
    get { return color; }
    set 
    { 
        color = value;
        RaisePropertyChnaged("Color");
    }
}

public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Color c = (Color)value;

        return new SolidColorBrush(c);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

==in xaml.cs==
private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(() => {
        mViewModel.Color = (Colors.Green);
    });
}