当selectitem数据被修改时,ListBox失去了更改selecteditem的能力

Übe*_*eil 8 wpf

一两天我一直试图找出一个奇怪的WPF错误.我有一个ListBox的控件绑定到PolicyId的ObservableCollection,它是一个类实现INotifyProperty和IEquatable,并且只有一个字段,称为Id(这是一个字符串).PolicyId是指向各种policicy项目的指针,这些项目修改了程序其他部分的工作流程.

ListBox绑定到集合,并且有一个添加和删除按钮,只需添加和删除Id到ListBox.还有一个下拉ComboBox,可用于将ListBox中selectedItem的PolicyId更改为另一个Id(可供选择的Id可在其他位置修改).当触发ComboBox.SelectionChanged事件时,在后端完成设置ListBox.SelectedItem.Id属性的值,并在触发ListBox.SelectionChanged事件时更改ComboBox中的值,这样可确保没有任何项目ListBox是完全相同的.

现在,这个实现大部分都有效.列表框中列出了所有策略,您可以添加新策略(在列表底部添加第一个可用的以前未选择的策略)并选择并删除您喜欢的任何策略.

只要您没有使用comboBox将一个策略替换为另一个策略,即.一旦你这样做,索引就会停留在你改变的那个上,你无法做出选择另一个策略的事情(设置ListBox.SelectedIndex没有效果).单击很长时间并最终抛出以下异常:"System.ArgumentException:已添加具有相同键的项目." 我怀疑错误是由WPF尝试将所选项添加到listBox的"selectedItems"集合引起的,即使该项已经存在或类似的东西.

我知道这个bug与PolicyId覆盖Equals有关(是的,我记得约束,如果Equals说两个对象彼此相等,那么GetHashCode也应该返回两个相同的值,所以GetHashCode也被覆盖)因为在程序的其他地方使用了类似的设置而没有任何问题.我不知道如何搞砸了,特别是因为集合中没有任何重复.

这是ListBox:

<ListBox Name="policyIdList" MinHeight="50" ItemsSource="{Binding Path=DataItem}" IsSynchronizedWithCurrentItem="True" SelectionChanged="policyIdList_SelectionChanged">
    <ListBox.Resources>
        <Style TargetType="ScrollViewer">
            <Setter Property="HorizontalScrollBarVisibility" Value="Hidden" />
        </Style>
    </ListBox.Resources>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock DataContext="{Binding Path=Id}" Text="{Binding Converter={StaticResource PolicyIdToName}}">
                <TextBlock.ToolTip>
                    <ContentControl Content="{Binding}" ContentTemplate="{StaticResource PolicyByOidListItem}" />
                </TextBlock.ToolTip>
            </TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)

而且,对于好的措施,comboBox:

<ComboBox Name="policyIdCombo" Grid.Row="1" Grid.Column="0"
ItemTemplate="{StaticResource PolicyByOidListItem}" SelectionChanged="policyIdCombo_SelectionChanged" />
Run Code Online (Sandbox Code Playgroud)

Cod*_*095 12

我认为问题是当你更改它的ID时你正在改变项的哈希码,而ListBox并不期望这样.有关更多信息,请参见此处

我刚刚将一个应用程序从.NET 3.5升级到4.0并遇到了这个问题.如果像我一样你无法使用固定的哈希码,那么解决方法是:

  1. 从列表中删除要更改的对象
  2. 通知UI的更改
  3. 更改对象的ID(导致更改其哈希码)
  4. 将对象添加回列表并通知UI更改.