代码之家  ›  专栏  ›  技术社区  ›  johnny g

ListBox正在选择许多项,即使在SelectionMode=“single”中也是如此

  •  7
  • johnny g  · 技术社区  · 15 年前

    我遇到了一些非常奇怪的,简单的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>
    

    有代码隐藏

    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 ();
        }
    }
    

    当我点击一个项目时,

    Why multiple values selected?

    如果我继续单击项目,它们只是聚合。单击已选择的项目不起任何作用。我抓耳挠腮,以前有列表框的数据绑定列表,以前从未见过。运行win7(64)、vs2010时,行为显示为.NET 3.5、.NET 3.5客户端配置文件、.NET 4和.NET 4客户端配置文件。

    arg,我应该提到我期望的是正常的、默认的、单一的选择行为。

    2 回复  |  直到 15 年前
        1
  •  11
  •   Robert Rossney    15 年前

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

    这里发生的事是在做绳索实习生。当您创建一组具有相同值的字符串时,.NET通过让所有对同一字符串值的引用实际上引用同一字符串对象来节省内存使用量。(见 this 例如,有关详细信息。)

    我真的不知道为什么列表框的行为和它的行为完全一样,也就是说,当您第一次选择列表中的任何项目时,它会同时选择该项目和列表中的第一个项目。但当您单击一个新项目时,它不会取消选择,因为它会检查 SelectedItem 与您刚才单击的项目不同,但没有。

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

    public class TestObject
    {
        public override string ToString()
        {
            return GetHashCode().ToString();
        }
    }
    

    MainWindow.xaml :

    <ListBox x:Name="MyListBox" ItemsSource={Binding}"/>
    

    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;
    
        2
  •  7
  •   Andy Pierre    15 年前

    我也遇到了这个问题,.NET以一种奇怪的方式处理字符串以改进内存管理。

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

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

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

            yourListBox.Items.Add(new UniqueListItemObject(yourStringHere);
    

    我不能说这是否是最好的解决方案(这取决于您的项目的需求),但希望有人会发现这很有用。

    推荐文章