即使在SelectionMode ="Single"中,ListBox也会选择很多项目

joh*_*y g 7 wpf binding listbox .net-4.0

我遇到过一些非常奇怪,简单的WPF应用程序

<Window x:Class="ListBoxSelection.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding Path=Strings}" SelectionMode="Single"/>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

代码背后

public class ViewModel
{
    public List<string> Strings { get; set; }

    public ViewModel ()
    {
        Strings = new List<string> ();
        Strings.Add ("A");
        // add many items ...
        Strings.Add ("A");
    }
}

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow ()
    {
        InitializeComponent ();

        DataContext = new ViewModel ();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我点击一个项目时,

为什么选择多个值?

如果我继续点击项目,他们只会聚合.单击已选择的项目不执行任何操作.抓我的头,我之前有数据包列表给ListBoxes,之前从未见过这个.运行Win7(64),VS2010,行为呈现.Net 3.5,.Net 3.5 Client Profile,.Net 4和.Net 4 Client Profile.

Arg,我应该提到我期待正常的,默认的,单选行为.

Rob*_*ney 11

丹·布莱恩特在评论中得到了大部分答案.

这里发生的是字符串实习.当您创建一组具有相同值的字符串时,.Net通过对相同字符串值的所有引用实际引用相同的字符串对象来节省内存使用量.(例如,有关详细信息,请参阅内容.)

我真的不知道为什么ListBox的行为与它完全一样,这是第一次选择列表中的任何项目时,它会同时选择该项目和列表中的第一项.但是当你点击一个新项目时它并没有取消选择,因为检查它是否与SelectedItem你刚刚点击的项目有所不同,但事实并非如此.

通过将ListBox绑定到测试对象的集合,我得到了完全相同的行为:

public class TestObject
{
    public override string ToString()
    {
        return GetHashCode().ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

MainWindow.xaml:

<ListBox x:Name="MyListBox" ItemsSource={Binding}"/>
Run Code Online (Sandbox Code Playgroud)

MainWindow.xaml.cs:

ObservableCollection<TestObject> test = new ObservableCollection<TestObject>();
TestObject t = new TestObject();
test.Add(t);
test.Add(t);
test.Add(t);
test.Add(t);
test.Add(t);
test.Add(t);
MyListBox.DataContext = test;
Run Code Online (Sandbox Code Playgroud)

  • @johnny g,我认为这是WPF背后的设计理念的一个工件,即列表框表示不同数据项的列表.您通常不会直接绑定字符串,而是将数据项呈现为字符串(通过DataTemplate或DisplayMember),这意味着您应该拥有唯一的数据项,即使在某些情况下呈现的字符串相同也是如此.如果您需要在具有相同表示的项目之间进行选择,您仍然需要一些数据对象来编码它们不同的方式(它们必须不同或者您没有两个选项) (2认同)
  • 如果非唯一项是预期的用例,那么`SelectedItem`将不是一个明智的属性. (2认同)

小智 7

我也遇到了这个问题 - 正如其他人所说,.NET以奇怪的方式处理字符串以改善内存管理.

我的直接解决方法是创建一个UniqueListItem类来代替我计划添加到列表框的字符串.

class UniqueListItemObject
{
    private string _text;
    public string Text { get { return _text; } set { _text = value; } }

    public UniqueListItemObject(string input)
    {
        Text = input;
    }
    public UniqueListItemObject()
    {
        Text = string.Empty;
    }

    public override string ToString()
    {
        return Text;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于此对象的每个实例都将获得其自己的内存位置,因此将此对象的实例添加到列表框控件而不是添加字符串将导致唯一选择,即使列表框中显示的字符串相同也是如此.

        yourListBox.Items.Add(new UniqueListItemObject(yourStringHere);
Run Code Online (Sandbox Code Playgroud)

我不能说这是否是最好的解决方案(这取决于你的项目的要求),但希望有人发现这有用.