pfinferno pfinferno - 12 days ago 5
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

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