当viewmodel变量更改时,在其他窗口中调用方法

时间:2016-11-22 14:25:11

标签: c# wpf

我有一个名为Timeline的窗口(不是我的主窗口),可以打开多次,传递不同的值。我想要做的是,当我的主窗口的viewmodel中更改了某个值时,我想在每个打开的Timeline窗口中调用一个方法。

这里是不断变化的变量。当它发生变化时,我想调用testDraw()函数(也在viewmodel中)。

private int _currentIteration;
public int CurrentIteration //used to hold current index of the list of data fields
{
    get { return _currentIteration; }
    set
    {
        _currentIteration = value;
        this.OnPropertyChanged("CurrentIteration");
    }
}

//Want to call this when CurrentIteration changes
public void testDraw()
{
    foreach (Timeline timeLineWin in Application.Current.Windows)
    {   
        Application.Current.Dispatcher.Invoke(new Action(() =>
        {
            timeLineWin.setCurrentValues(CurrentIteration);
            timeLineWin.linechart1.HighlightPoint(timeLineWin.currentX, timeLineWin.currentY);
        }));
        //linechart1 is a winforms component on the timeline window   
    }            
}

这是时间线窗口背后的代码:

public partial class Timeline : Window
{
    public List<double> xValues;
    public List<double> yValues;
    public double currentX;
    public double currentY;

    public Timeline(List<double> x, List<double> y)
    {
        InitializeComponent();
        xValues = x;
        yValues = y;
    }

    public void setCurrentValues(int i)
    {
        currentX = xValues[i];
        currentY = yValues[i];
    }
}

功能&#39; testDraw()&#39;应该遍历所有当前打开的Timeline窗口并调用这些窗口中的两个函数。

我得到的错误是:

The calling thread cannot access this object because a different thread owns it. - 所以我尝试在方法中使用Dispatcher.Invoke也没有用。

注意:我不确定如何将此位保留在MVVM格式中。

2 个答案:

答案 0 :(得分:1)

您是否考虑过使用EventAggregator在Windows之间进行通信?用户界面线程上有一个subscribign选项:https://msdn.microsoft.com/en-us/library/ff921122.aspx

构造每个时间线对象时,订阅

eventAggregator.GetEvent<IterationChangeEvent>().Subscribe(UpdateUI, ThreadOption.UIThread);

private void UpdateUI(Iteration iteration)
{
    this.setCurrentValues(iteration);
    this.linechart1.HighlightPoint(this.currentX, this.currentY);
}        

在CurrentIteration更改调用的主窗口中:

eventAggregator.GetEvent<IterationChangeEvent>().Publish(this.currentIteration);

你的活动课程会像这样:

public class IterationChangeEvent : CompositeWpfEvent<int>
{
}

答案 1 :(得分:1)

您必须在testDraw中调用整个Dispatcher方法,因为即使是Application.Current.Windows的获取者也需要它:

public void testDraw()
{
    Application.Current.Dispatcher.Invoke(new Action(() =>
    {
        foreach (Timeline timeLineWin in Application.Current.Windows)
        {
            timeLineWin.setCurrentValues(CurrentIteration);
            timeLineWin.linechart1
                .HighlightPoint(timeLineWin.currentX, timeLineWin.currentY);
        }
    }));
}