Ok, it took me quite a while to find the root cause of your problem.
Unlike from what others suspected, this isn't a multithreading issue at all.
Instead it's an issue with the DynamicDataDisplay
library you are using.
There's a clear reason why your ItemsSource
binding works on your ListBox
object and doesn't work on Chart
(of type Microsoft.Research.DynamicDataDisplay.Markers2.LineChart
) :
Chart
neither has a visual nor a logical parent.
You can check this if you insert the following code into Button_Click
and set a breakpoint after them:
var visualParent = VisualTreeHelper.GetParent(Chart);
var logicalParent1 = Chart.Parent;
var logicalParent2 = LogicalTreeHelper.GetParent(Chart);
You can see that they are all null
.
So the Binding
that you set on LineChart.ItemsSourceProperty
with Path=ExampleCollection
cannot find any source value and just assigns null
to the ItemsSource
. That's because the DataContext
is inherited from the parent - but when there isn't any parent then there isn't any DataContext
to inherit either.
And because Chart
isn't part of the visual or logical tree, there is no (easy) way any binding to an outside DataContext
can even work.
To verify that the DataContext
is null
just add this line to the preceding code:
var dataContext = Chart.DataContext;
Now there are three possible solutions for this.
First, you can manually inherit the DataContext
from Window
using the following code:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Just add the following line.
Chart.DataContext = DataContext;
Chart.StrokeThickness = 3;
Chart.SetBinding(LineChart.ItemsSourceProperty, new Binding("ExampleCollection"));
// ...
}
If you simply add this one line, you'll see that your other multithreaded code is working just fine and the chart is updated with some kind of sine wave pattern.
Second, as another possible solution you can consult the documentation for the DynamicDataDisplay
library and check the correct and intended way to assign an ItemsSource
to a LineChart
using data binding.
I tried searching for documentation myself and even debugged a lot of code from that library for two hours or so, but the documentation is nearly non-existent and the code is far too complex to fully understand it in a few hours. I tried using several tools (Visual Studio Live Visual Tree, Snoop, ...) for displaying the visual tree of the ChartPlotter
but I got a StackOverflowException
every time, so essentially something in this library is kind of flawed and buggy.
Third, you can use a Resource
as a kind of proxy object to create a "binding bridge" to the same instance of the MainWindowViewModel
.
For this to work, you have to do something like suggested here: Data binding outside the visual tree. Data Context bridging
Bottom line: So, if you just want to get the job done, I would set the DataContext
in code like shown above. (Especially if the instance of the ViewModel
in the DataContext
never changes.)
If you want to use pure data binding then I would probably use the "binding bridge" or search for another charting library that supports this scenario.