I have a xamDiagram whose diagram items are populated from a view model using TwoWay data binding, as per the XamDiagram documentation.
For the most part, this works as intended, in that I can modify the diagram item objects in the view model or their respective objects in the diagram, and the TwoWay binding ensures that changes save in both directions. However, there is a really strange case in which the data binding will fail when updating the data in the view model and throw an exception when calling NotifyPropertyChanged on the object.
Note: My data objects in the view model contain most of the same properties that exist on the DiagramItem/Node/Connections in the diagram (e.g., Fill, Position, Stroke, Width, Height, ShapeType)
The exception generally looks like this:
Exception thrown: 'System.Collections.Generic.KeyNotFoundException' in mscorlib.dllException thrown: 'System.Reflection.TargetInvocationException' in mscorlib.dllSystem.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=Content.Position; DataItem='DiagramNode' (Name=''); target element is 'DiagramNode' (Name=''); target property is 'Position' (type 'Point') KeyNotFoundException:'System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Generic.Dictionary`2.get_Item(TKey key) at Infragistics.Controls.Charts.XamDiagram.PropertyChangedWeakCollectionChanged(IFastItemsSource fastItemsSource, Object sender, PropertyChangedEventArgs args) at Infragistics.ItemSourceEventProxy.propertyChanged(Object sender, PropertyChangedEventArgs e) at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e) at GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged(String propertyName) at Sandbox.Custom.SandboxSketchDiagram.Items.SketchDiagramNode.set_Position(Point value) in C:\Users\afink\Sandbox\Sandbox\Custom\SandboxSketchDiagram\Items\SketchDiagramNode.cs:line 26'
Exception thrown: 'System.Collections.Generic.KeyNotFoundException' in mscorlib.dll
Exception thrown: 'System.Reflection.TargetInvocationException' in mscorlib.dll
System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=Content.Position; DataItem='DiagramNode' (Name=''); target element is 'DiagramNode' (Name=''); target property is 'Position' (type 'Point') KeyNotFoundException:'System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Infragistics.Controls.Charts.XamDiagram.PropertyChangedWeakCollectionChanged(IFastItemsSource fastItemsSource, Object sender, PropertyChangedEventArgs args)
at Infragistics.ItemSourceEventProxy.propertyChanged(Object sender, PropertyChangedEventArgs e)
at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
at GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged(String propertyName)
at Sandbox.Custom.SandboxSketchDiagram.Items.SketchDiagramNode.set_Position(Point value) in C:\Users\afink\Sandbox\Sandbox\Custom\SandboxSketchDiagram\Items\SketchDiagramNode.cs:line 26'
where SketchDiagramNode.cs:line 26 is where NotifyPropertyChanged() is being executed in the object being updated in the view model. Again, this only happens occasionally.
SketchDiagramNode.cs:line 26
Also, here is what the data binding looks like for the items in the ItemsSource collection in my diagram:
<Style x:Key="DiagramItemStyle" TargetType="ig:DiagramItem"> <Setter Property="Fill" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Fill, Mode=TwoWay}" /> <Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Visibility, Mode=TwoWay}" /> <Setter Property="IsEnabled" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Visibility, Converter={StaticResource ResourceKey=VisibilityToBoolConverter}}" /> <Setter Property="Stroke" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Stroke, Mode=TwoWay}" /> <Setter Property="StrokeThickness" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.StrokeThickness, Mode=TwoWay}" /> <Setter Property="StrokeDashArray" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.StrokeDashArray, Mode=TwoWay}" /> <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Foreground, Mode=TwoWay}" /> <Setter Property="FontFamily" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.FontFamily, Mode=TwoWay}" /> <Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.FontSize, Mode=TwoWay}" /> <Setter Property="FontStyle" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.FontStyle, Mode=TwoWay}" /> <Setter Property="FontWeight" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.FontWeight, Mode=TwoWay}" /> <Setter Property="Opacity" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Opacity, Mode=TwoWay}" /> <Setter Property="ZIndex" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.ZIndex, Mode=TwoWay}" /> </Style> <Style x:Key="DiagramNodeStyle" TargetType="ig:DiagramNode" BasedOn="{StaticResource ResourceKey=DiagramItemStyle}"> <Setter Property="Position" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Position, Mode=TwoWay}" /> <Setter Property="ShapeType" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.ShapeType, Mode=TwoWay}" /> <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Width, Mode=TwoWay}" /> <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Height, Mode=TwoWay}" /> <Setter Property="MaintainAspectRatio" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.MaintainAspectRatio, Mode=TwoWay}" /> </Style>
I have tried to create a minimal reproducible example project to recreate the error, but I have yet to succeed in reproducing the error on a new test project, so I still don't know what is causing it or what I may be doing wrong.
I know this could be pretty difficult to diagnose without any kind of example code to reproduce it, but I was wondering if you guys knew of anything that I could be generally doing wrong when using two-way binding on the ItemsSource collection in the xamDiagram that could cause this exception to be thrown?
Thanks for the quick response!
1. The exception occurs when any property is updated on the data object (in the view model) programmatically, followed by the user dragging the corresponding DiagramNode around in the diagram. It makes no sense to me, as this only occurs when updating some, but not all, of the properties on the object.
2. I am currently binding the Position property of the DiagramNode to the Position property of its corresponding data object in the view model. Here is what the data object class definition and the Nodes collection definition in the view model look like. The Nodes collection on the view model is being bound to the ItemsSource property on the XamDiagram.
// My data object class SketchDiagramNode { // Omitting other properties private Point m_position; public Point Position { get => m_position; set { if (value.Equals(m_position)) return; m_position = value; RaisePropertyChanged(); } } } // View model definition // The Nodes collection is bound to the XamDiagram.ItemsSource property class MyViewModel { private ObservableCollection<SketchDiagramNode> m_nodes = new ObservableCollection<SketchDiagramNode>(); public ObservableCollection<SketchDiagramNode> Nodes { get => m_nodes; set { if (m_nodes == value) return; m_nodes = value; RaisePropertyChanged(); } } }
3. I have attached my test project where I have been attempting to reproduce the error. Note: I have not yet been able to reproduce the error in the test project, but with it you should at least be able to see how I am using the XamDiagram, which may give you some insight into figuring out if I'm doing anything wrong.
Here's a google drive link to the project file: Test Project
Hello Andrew,
I have been investigating into the behavior you are seeing, and I have a few questions for you on this matter. Would it be possible for you to please provide some information on the following?
1. What is the action that you or the user is taking when this exception occurs? By chance is it while moving a node? I ask, as I see a binding issue in the trace you provided complaining about the binding to Content.Position of the DiagramNode.
2. What are you currently binding the Position of your node to?
3. Would it be possible for you to please attach the “minimal reproducible example project” that you created to try to reproduce the behavior here?
Please let me know if you have any other questions or concerns on this matter.