我有一个名为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格式中。
答案 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);
}
}));
}