Mvvm绑定投掷

时间:2015-02-04 14:26:28

标签: c# wpf multithreading mvvm

我有一个使用Mvvm Light的项目,在线程中,应用程序抛出异常。

  

必须在与dependencyobject相同的线程上创建dependencysource。

我使用CanvasPolyLine

<Canvas Name="canvas1" SizeChanged="canvas1_SizeChanged" >
 <Polyline Points="{Binding SegmentPoints}" Stroke="Black" StrokeThickness="1.5"/>
</Canvas>

在我的ViewModel中,我有一个名为SegmentPoints

的属性
private PointCollection segmentPoints;
public PointCollection SegmentPoints
        {
            get { return segmentPoints; }
            set {segmentPoints = value;    
                RaisePropertyChanged("SegmentPoints");
            }
        }

我有一个Thread,它在后台运行。

var p = new ParameterizedThreadStart(StartMeassureThread);
Thread t = new Thread(p);
t.Start(package);

StartMeassureThread我调用updatePointCollection函数:

segmentPoints = new PointCollection();
...somecode
RaisePropertyChanged("SegmentPoints");

它引发了一个例外:

  

用户代码未处理ArgumentException。

内部

protected virtual void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(
                this,
                new PropertyChangedEventArgs(propertyName));
        }
    }

有人可以帮帮我吗?非常感谢你提前。

2 个答案:

答案 0 :(得分:1)

您无法从UI线程以外的线程更改UI。要进行同步,您可以使用MVVMLight提供的DispatcherHelper.CheckBeginInvokeOnUI方法:

var value = CreateSegmentPoints();
DispatcherHelper.CheckBeginInvokeOnUI(()=> SegmentPoints = value);

答案 1 :(得分:0)

当后台线程设置SegmentPoint并且View绑定到此属性时,后台线程将用于更改UI。这将导致异常,因为只允许UI线程更新UI。

可以通过在ViewModel的RaisePropertyChanged中切换到View的Dispatcher来进行快速修复。要做到这一点,你需要以某种方式捕获UI线程。例如,将ViewModel附加到View时将其传递给构造函数。

对于更动态的情况,您可能希望订阅View的DataContextChanged并在那里设置正确的线程。