【问题标题】:Strange behaviour when binding to ListBox in WPF在 WPF 中绑定到 ListBox 时的奇怪行为
【发布时间】:2011-05-18 20:06:23
【问题描述】:

在将数组绑定到 ListBox 时,我注意到一些奇怪的行为。当我添加具有相同“名称”的项目时,我无法在运行时选择它们 - ListBox 发疯了。如果我给他们独特的“名字”,它就可以了。谁能解释一下为什么会发生这种情况?

观点:

<Window x:Class="ListBoxTest.ListBoxTestView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ListBoxTest"
        Title="ListBoxTestView" Height="300" Width="300">
    <Window.Resources>
        <local:ListBoxTestViewModel x:Key="Model" />
    </Window.Resources>
    <Grid DataContext="{StaticResource ResourceKey=Model}">
        <ListBox ItemsSource="{Binding Items}" Margin="0,0,0,70" />
        <Button Command="{Binding Path=Add}"  Content="Add" Margin="74,208,78,24" />
    </Grid>
</Window>

视图模型:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;

namespace ListBoxTest
{
    internal class ListBoxTestViewModel : INotifyPropertyChanged
    {
        private List<string> realItems = new List<string>();

        public ListBoxTestViewModel()
        {
            realItems.Add("Item A");
            realItems.Add("Item B");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public string[] Items
        {
            get { return realItems.ToArray(); }
        }

        public ICommand Add
        {
            // DelegateCommand from Prism
            get { return new DelegateCommand(DoAdd); }
        }

        private int x = 1;
        public void DoAdd()
        {
            var newItem = "Item";
            // Uncomment to fix
            //newItem += " " + (x++).ToString();
            realItems.Add(newItem);
            OnPropertyChanged("Items");
        }
    }
}

【问题讨论】:

    标签: wpf data-binding listbox binding


    【解决方案1】:

    WPF ListBox 中的所有项目都必须是唯一的实例。由于字符串 Interning,具有相同常量值的字符串不是唯一实例。为了解决这个问题,您需要将 item 封装在比 String 更有意义的对象中,例如:

    public class DataItem 
    { 
        public string Text { get; set; } 
    }
    

    现在您可以实例化多个 DataItem 实例并创建一个 ItemDataTemplate 以将 Text 呈现为 TextBlock。如果要使用默认呈现,还可以覆盖 DataItem ToString()。您现在可以拥有多个具有相同文本且没有问题的 DataItem 实例。

    这个限制可能看起来有点奇怪,但它简化了逻辑,因为现在 SelectedItem 与列表中的项目的 SelectedIndex 是一一对应的。它也符合 WPF 数据可视化方法,该方法倾向于有意义的对象列表,而不是纯字符串列表。

    【讨论】:

    • 这实际上不是关于唯一实例(引用相等),而是关于逻辑相等(虚拟 Equals 方法)。如果两个字符串具有相同的内容,即使它们是不同的引用,您也会从 ListBox 中得到奇怪的行为。但是,是的,将它们包装在不覆盖 Equals 的引用类型中应该可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2011-01-02
    相关资源
    最近更新 更多