pfinferno pfinferno - 8 months ago 52
C# Question

Call methods in other windows when viewmodel variable changes

I have a window called

Timeline
(not my mainwindow), that can be opened several times with different values being passed. What I'm trying to do is, when a certain value is changed in my viewmodel for my main window, I want to call a method in each
Timeline
window that is open.

Here's the variable that is constantly changing. When it does change, I want to call the testDraw() function (also in the 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
}
}


Here's the code behind for 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];
}
}


The function 'testDraw()' is supposed to loop through all the currently open
Timeline
windows and call the two functions in those windows.

The error I got was:

The calling thread cannot access this object because a different thread owns it.
- So I tried using
Dispatcher.Invoke
in the method which also did not work.

Note: I wasn't sure how to keep this bit in the MVVM format.

Answer Source

You have to invoke your whole testDraw method in the Dispatcher because even the getter of Application.Current.Windows requires it:

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);
        }
    }));
}