WPF组合框无法正确更新

时间:2012-09-28 22:19:41

标签: c# wpf data-binding combobox

我正在尝试在其SelecteItem属性上使用带有数据绑定的WPF组合框。当用户选择新选择时,SelectedItem会更改,但我的模型未正确更新,并且SelectionBoxItem(组合框中显示的项目)不会更改。

更具体地说,我有以下两个要素:

<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>

此listview按预期工作。有问题的组合框定义如下

<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>

因此,当用户从ListView(上面)中选择一个节点时,ComboBox会更新以显示该节点正在使用的摄像头。

现在奇怪的行为。如果用户单击组合框上的新项,我可以使用调试器停止并检查SelecteItem属性。这始终设置正确,但CurrentNode.NodeInfo.Camera1属性不会更改,并且“SelectionBox”中显示的字符串不会更改。

然而,它变得更加陌生。如果用户在ComboBox上进行此类选择后切换节点(使用前面定义的ListView),则ComboBox不再显示新值,但SelectedItem是正确的。如果用户然后更改ListView AGAIN中的所选项目,则它开始显示正确的值,并且一直很好,直到用户再次使用组合框混乱。

现在我早些时候说过,当ComboBox发生变化时我的模型没有被更新,所以我创建了一个事件处理程序来为我更新模型(你可以在ComboBox的定义中看到这一点)。这被定义为可能的

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
        }
    }

当我注释掉上面列表中的标记行时,ComboBox会在SelectionBox中显示正确的项目,但不会更新我的模型(例如CurrentNode.NodeInfo.Camera1未更改)。当我使用lvNodes.SelectedItem或当我使用CurrentCamera(数据绑定属性)时,会发生这种情况,它没有区别。

我知道这是一个非常奇怪的问题,如果有人想要更多信息(数据绑定的调试输出,转换器的代码,有关相等运算符的信息等),我会尽力解释它,我很乐意提供它,如果有必要的话,我会愿意上传一段显示奇怪行为的视频,因为它有点难以从文本中理解。

更新

转换器代码

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

调试输出

在加载时:

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)

在选择框中未显示的组合框上进行选择后:

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)

将ListView切换到新节点,选择框仍未更新:

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)

使用DID更新选择框的列表视图切换节点后:

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)

3 个答案:

答案 0 :(得分:1)

我认为您的问题与您绑定SelectedItem的方式有关:

<ComboBox ...
    SelectedItem="{Binding Path=CurrentNode.NodeInfo.Camera1, 
        Converter={StaticResource EnsureBlank}, Mode=TwoWay}"  ...

如果内存正常,SelectedItem是一个属性(Text是另一个属性)(默认情况下)仅在焦点丢失时推送更新。

UpdateSourceTrigger="PropertyChanged"添加到绑定以强制更新更频繁地发生。你不应该需要你的活动。

答案 1 :(得分:0)

您的转换器会创建一个新对象,而ItemTemplate的TextBlock中的文本将保持与原始对象的绑定。因此,当您更改新对象的Name属性时,它显然不会改变。

答案 2 :(得分:0)

好的,所以我最终完全摆脱了数据绑定,并使用一个非常winforms样式的事件模型来更新我的数据。我仍然无法弄清楚为什么数据绑定不起作用,如果有人使用数据绑定解决方案我会接受这个答案。