Ok, es hat eine Weile gedauert, bis ich die Ursache des Problems gefunden habe.
Im Gegensatz zu dem, was andere vermutet haben, ist dies kein Multithreading-Problem.
Stattdessen ist es ein Problem mit der DynamicDataDisplay
Bibliothek, die Sie verwenden.
Es gibt einen klaren Grund, warum Ihre ItemsSource
Bindung Arbeiten auf Ihrem ListBox
Objekt und nicht auf Chart
funktionieren (vom Typ Microsoft.Research.DynamicDataDisplay.Markers2.LineChart
):
Chart
hat weder einen visuellen noch einen logischen Elternteil.
Sie können dies überprüfen, ob Sie den folgenden Code in Button_Click
und gesetzt, nachdem sie einen Breakpoint einfügen:
var visualParent = VisualTreeHelper.GetParent(Chart);
var logicalParent1 = Chart.Parent;
var logicalParent2 = LogicalTreeHelper.GetParent(Chart);
Sie sehen können, dass sie alle null
sind.
So die Binding
, die Sie auf LineChart.ItemsSourceProperty
mit Path=ExampleCollection
festgelegt haben, kann keinen Quellwert finden und weist null
nur dem ItemsSource
zu. Das liegt daran, dass die DataContext
vom übergeordneten Element geerbt wird. Wenn jedoch kein übergeordnetes Element vorhanden ist, wird kein DataContext
erben.
Und weil Chart
nicht Teil des visuellen oder logischen Baumes ist, gibt es keine (einfache) Möglichkeit, eine Bindung an eine Außenseite DataContext
kann sogar funktionieren.
Um sicherzustellen, dass die DataContext
ist null
gerade diese Linie zu dem vorhergehenden Code hinzu:
var dataContext = Chart.DataContext;
Nun gibt es für diese drei mögliche Lösungen.
Erste, können Sie die DataContext
von Window
mit dem folgenden Code manuell erben können:
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"));
// ...
}
Wenn Sie diese eine Zeile einfach hinzufügen, werden Sie Ihre anderen multithreaded Code funktioniert ganz gut und das Diagramm sehen, dass wird mit einer Art Sinuswellenmuster aktualisiert.
Zweite, als eine weitere mögliche Lösung, die Sie in der Dokumentation der DynamicDataDisplay
Bibliothek konsultieren und überprüfen Sie die bestimmungsgemäße Art und Weise verbindlich ein ItemsSource
auf eine LineChart
unter Verwendung von Daten zuzuweisen.
Ich habe selbst versucht, nach Dokumentation zu suchen und habe sogar zwei Stunden lang viel Code aus dieser Bibliothek getestet, aber die Dokumentation ist fast nicht vorhanden und der Code ist viel zu komplex, um ihn in ein paar Stunden vollständig zu verstehen. Ich habe versucht, mehrere Werkzeuge (Visual Studio Live Visual Tree, Snoop, ...) für die Anzeige der visuellen Baum der ChartPlotter
, aber ich habe ein StackOverflowException
jedes Mal, so im Wesentlichen etwas in dieser Bibliothek ist eine Art von Fehlern und Buggy.
Third, können Sie eine Resource
als eine Art Proxy-Objekt verwenden, um eine „Bindungsbrücke“ auf die gleiche Instanz des MainWindowViewModel
zu erstellen.
Damit dies funktioniert, müssen Sie hier vorgeschlagen, etwas zu tun wie: Data binding outside the visual tree. Data Context bridging
Unterm Strich: Also, wenn Sie nur die Arbeit erledigt erhalten möchten, würde ich die DataContext
im Code festgelegt, wie oben gezeigt. (Vor allem, wenn die Instanz der ViewModel
in der DataContext
nie ändert.)
Wenn Sie reine Datenbindung verwenden möchten, würde ich wahrscheinlich die "binding bridge" oder suchen Sie nach einer anderen Charting-Bibliothek, die dieses Szenario unterstützt.
Mögliches Duplikat von [ObservableCollection und threading] (http://stackoverflow.com/questions/2293246/observablecollection-and-threading) – dymanoid
Es würde wirklich helfen, wenn Sie die 'StackTrace' oder zumindest die' Nachricht' posten könnten Ihrer 'InvalidOperationException'. – haindl
@haindl meine schlechte, fügte hinzu –