Reputation: 2525
I am trying to use a WPF combobox with a databinding on its SelecteItem
property. When the user chooses a new selection, the SelectedItem
changes, but my model is not updated properly, and the SelectionBoxItem
(item displayed in the combobox) is not changed.
More specifically, I have the following two elements:
<ListView Name="lvNodes" ItemsSource="{Binding Path=Nodes}" SelectedItem="{Binding Path=CurrentNode, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This listview works as expected. The combobox that is having problems is defined like so
<ComboBox ItemsSource="{Binding Path=CameraViews}" SelectedItem="{Binding Path=CurrentNode.NodeInfo.Camera1, Converter={StaticResource EnsureBlank}, Mode=TwoWay}" Name="comboBoxTopCam" SelectionChanged="comboBoxTopCam_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
So when the user selects a node from the ListView (above), the ComboBox updates to display the camera that node is using.
Now the strange behavior. If the user clicks on a new item on the combo box, I can stop with the debugger and examine the SelecteItem
property. This is always set properly, however the CurrentNode.NodeInfo.Camera1
property is not changed, and the string displayed in the "SelectionBox" is unchanged.
It gets even stranger, however. If the user switches the node (using the ListView defined earlier) AFTER making such a selection on the ComboBox, the ComboBox again doesn't display the new value, but the SelectedItem
is correct. If the user then changes the selected item in the ListView AGAIN, then it starts displaying the correct value, and is fine until the user messes with the combo box again.
Now I said earlier that my model is not being updated when the ComboBox changes, so I made an event handler to update the model for me (you can see this in the definition of the ComboBox). This is defined as possible
private void comboBoxTopCam_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
CameraViewInfo selCam = comboBoxTopCam.SelectedItem as CameraViewInfo;
if (selCam != null)
{
OTNode selNode = lvNodes.SelectedItem as OTNode;
if (selCam.Name == "None")
selNode.NodeInfo.Camera1 = new CameraViewInfo();
else
selNode.NodeInfo.Camera1 = selCam; // <- This line affects the behavior
}
}
When I comment out the marked line in the above listing, the ComboBox displays the correct item in the SelectionBox, but doesn't update my model (e.g. CurrentNode.NodeInfo.Camera1
is not changed). This happens when I use lvNodes.SelectedItem
OR when I use CurrentCamera
(the databound property), it makes no difference which.
I know this is a pretty weird problem, and I did the best I could explaining it, if anyone wants more information (debug output from databindings, code for the converter, information about equality operators etc) I am happy to provide it, I would event be willing to upload a video showing the odd behavior if necessary, since its a little hard to make sense of from text alone.
Update:
public class EnsureBlankConterter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is CameraViewInfo)
{
if ((value as CameraViewInfo).Name == "")
{
return new CameraViewInfo()
{
Name = "None"
};
}
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is CameraViewInfo)
{
if ((value as CameraViewInfo).Name == "None")
{
return new CameraViewInfo();
}
}
return value;
}
}
PresentationTraceSource.High
At load time:
System.Windows.Data Warning: 54 : Created BindingExpression (hash=45045097) for Binding (hash=10919470)
System.Windows.Data Warning: 56 : Path: 'CurrentNode.NodeInfo.Camera1'
System.Windows.Data Warning: 60 : BindingExpression (hash=45045097): Attach to System.Windows.Controls.ComboBox.SelectedItem (hash=34909671)
System.Windows.Data Warning: 65 : BindingExpression (hash=45045097): Resolving source
System.Windows.Data Warning: 68 : BindingExpression (hash=45045097): Found data context element: ComboBox (hash=34909671) (OK)
System.Windows.Data Warning: 76 : BindingExpression (hash=45045097): Activate with root item ConfigurationWindow (hash=22010384)
System.Windows.Data Warning: 105 : BindingExpression (hash=45045097): At level 0 using cached accessor for ConfigurationWindow.CurrentNode: RuntimePropertyInfo(CurrentNode)
System.Windows.Data Warning: 102 : BindingExpression (hash=45045097): Replace item at level 0 with ConfigurationWindow (hash=22010384), using accessor RuntimePropertyInfo(CurrentNode)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): <null>
System.Windows.Data Warning: 104 : BindingExpression (hash=45045097): Item at level 1 is null - no accessor
System.Windows.Data Warning: 101 : BindingExpression (hash=45045097): Replace item at level 2 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=45045097): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 86 : BindingExpression (hash=45045097): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 87 : BindingExpression (hash=45045097): TransferValue - using final value <null>
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): OTNode (hash=59090892)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): OTNode (hash=59090892)
System.Windows.Data Warning: 106 : BindingExpression (hash=45045097): At level 1 - for OTNode.NodeInfo found accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 102 : BindingExpression (hash=45045097): Replace item at level 1 with OTNode (hash=59090892), using accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 1 from OTNode (hash=59090892) using ReflectPropertyDescriptor(NodeInfo): OTNodeInfo (hash=34742292)
System.Windows.Data Warning: 106 : BindingExpression (hash=45045097): At level 2 - for OTNodeInfo.Camera1 found accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 102 : BindingExpression (hash=45045097): Replace item at level 2 with OTNodeInfo (hash=34742292), using accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 2 from OTNodeInfo (hash=34742292) using ReflectPropertyDescriptor(Camera1): CameraViewInfo (hash=29245900)
System.Windows.Data Warning: 78 : BindingExpression (hash=45045097): TransferValue - got raw value CameraViewInfo (hash=29245900)
System.Windows.Data Warning: 80 : BindingExpression (hash=45045097): TransferValue - user's converter produced CameraViewInfo (hash=29245900)
System.Windows.Data Warning: 87 : BindingExpression (hash=45045097): TransferValue - using final value CameraViewInfo (hash=29245900)
After making a selection on the combo box that wasn't displayed in the selection box:
System.Windows.Data Warning: 88 : BindingExpression (hash=45045097): Update - got raw value CameraViewInfo (hash=7936647)
System.Windows.Data Warning: 90 : BindingExpression (hash=45045097): Update - user's converter produced CameraViewInfo (hash=7936647)
System.Windows.Data Warning: 92 : BindingExpression (hash=45045097): Update - using final value CameraViewInfo (hash=7936647)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): OTNode (hash=59090892)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 1 from OTNode (hash=59090892) using ReflectPropertyDescriptor(NodeInfo): OTNodeInfo (hash=22129877)
Switching the ListView to a new node, the Selection Box still didn't update:
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): OTNode (hash=63206919)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 0 from ConfigurationWindow (hash=22010384) using RuntimePropertyInfo(CurrentNode): OTNode (hash=63206919)
System.Windows.Data Warning: 106 : BindingExpression (hash=45045097): At level 1 - for OTNode.NodeInfo found accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 102 : BindingExpression (hash=45045097): Replace item at level 1 with OTNode (hash=63206919), using accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 1 from OTNode (hash=63206919) using ReflectPropertyDescriptor(NodeInfo): OTNodeInfo (hash=35582358)
System.Windows.Data Warning: 106 : BindingExpression (hash=45045097): At level 2 - for OTNodeInfo.Camera1 found accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 102 : BindingExpression (hash=45045097): Replace item at level 2 with OTNodeInfo (hash=35582358), using accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 99 : BindingExpression (hash=45045097): GetValue at level 2 from OTNodeInfo (hash=35582358) using ReflectPropertyDescriptor(Camera1): CameraViewInfo (hash=49590542)
System.Windows.Data Warning: 78 : BindingExpression (hash=45045097): TransferValue - got raw value CameraViewInfo (hash=49590542)
System.Windows.Data Warning: 80 : BindingExpression (hash=45045097): TransferValue - user's converter produced CameraViewInfo (hash=49590542)
System.Windows.Data Warning: 87 : BindingExpression (hash=45045097): TransferValue - using final value CameraViewInfo (hash=49590542)
After switching the node using the list view that DID update the selection box:
System.Windows.Data Warning: 99 : BindingExpression (hash=51217614): GetValue at level 0 from ConfigurationWindow (hash=63245828) using RuntimePropertyInfo(CurrentNode): OTNode (hash=8023662)
System.Windows.Data Warning: 99 : BindingExpression (hash=51217614): GetValue at level 0 from ConfigurationWindow (hash=63245828) using RuntimePropertyInfo(CurrentNode): OTNode (hash=8023662)
System.Windows.Data Warning: 106 : BindingExpression (hash=51217614): At level 1 - for OTNode.NodeInfo found accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 102 : BindingExpression (hash=51217614): Replace item at level 1 with OTNode (hash=8023662), using accessor ReflectPropertyDescriptor(NodeInfo)
System.Windows.Data Warning: 99 : BindingExpression (hash=51217614): GetValue at level 1 from OTNode (hash=8023662) using ReflectPropertyDescriptor(NodeInfo): OTNodeInfo (hash=21425964)
System.Windows.Data Warning: 106 : BindingExpression (hash=51217614): At level 2 - for OTNodeInfo.Camera1 found accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 102 : BindingExpression (hash=51217614): Replace item at level 2 with OTNodeInfo (hash=21425964), using accessor ReflectPropertyDescriptor(Camera1)
System.Windows.Data Warning: 99 : BindingExpression (hash=51217614): GetValue at level 2 from OTNodeInfo (hash=21425964) using ReflectPropertyDescriptor(Camera1): CameraViewInfo (hash=6049320)
System.Windows.Data Warning: 78 : BindingExpression (hash=51217614): TransferValue - got raw value CameraViewInfo (hash=6049320)
System.Windows.Data Warning: 80 : BindingExpression (hash=51217614): TransferValue - user's converter produced CameraViewInfo (hash=6049320)
System.Windows.Data Warning: 87 : BindingExpression (hash=51217614): TransferValue - using final value CameraViewInfo (hash=6049320)
Upvotes: 0
Views: 2780
Reputation: 2525
Ok so I ended up getting rid of the databindings altogether and using a very winforms style event model to update my data. I still cannot figure out why the databindings don't work, if anyone has a solution using databindings I will accept that as the answer.
Upvotes: 0
Reputation: 2944
Your converter creates a new object, while the text in the ItemTemplate's TextBlock stays bound to the original object. So, obviously it will not change when you change the new object's Name property.
Upvotes: 0
Reputation: 44307
I think your problem is with the way you're binding to SelectedItem
:
<ComboBox ...
SelectedItem="{Binding Path=CurrentNode.NodeInfo.Camera1,
Converter={StaticResource EnsureBlank}, Mode=TwoWay}" ...
If memory serves correctly, SelectedItem
is one property (Text
is another) that (by default) only pushes updates through when focus is lost.
Add UpdateSourceTrigger="PropertyChanged"
to the binding to force the update to happen more frequently. You shouldn't need your event.
Upvotes: 1