用于表示ComboBox的空值的特殊项

时间:2016-09-06 13:47:18

标签: c# wpf mvvm data-binding combobox

我正在使用MVVM模式在WPF中实现用户控件。我希望控件包含ItemsControl,特别是ComboBox,其中包含人员列表。我希望第一个菜单项标记为“No Person'并绑定到数据源上的null,而其余项是绑定到Person个对象的人的名称。

Person的代码和视图模型如下:

namespace NoValueItem
{
    public class Person : IEquatable<Person>
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public static bool Equals(Person a, Person b)
        {
            if (a == null)
                return b == null;
            return a.Equals(b);
        }

        public bool Equals(Person other)
        {
            if (ReferenceEquals(this, other))
                return true;
            if (ReferenceEquals(null, other))
                return false;
            return this.Name.Equals(other.Name);
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as Person);
        }

        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }
    }

    public class ViewModel : INotifyPropertyChanged
    {

        public ObservableCollection<Person> ListOfPersons { get; } =
            new ObservableCollection<Person> {
                null,
                new Person() { Id = 1, Name = "Alice" },
                new Person() { Id = 2, Name = "Bob" },
                new Person() { Id = 3, Name = "Charlie" }
            };


        private Person _SelectedPerson;

        public Person SelectedPerson
        {
            get
            {
                return _SelectedPerson;
            }
            set
            {
                if (!Person.Equals(value, _SelectedPerson)) {
                    _SelectedPerson = value;
                    OnPropertyChanged();
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class NullSubstituteConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value ?? parameter;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (parameter == null)
                return value;
            return parameter.Equals(value) ? null : value;
        }
    }
}

观点:

<Window x:Class="NoValueItem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NoValueItem"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid d:DataContext="{d:DesignInstance local:ViewModel}" VerticalAlignment="Center">
        <Grid.DataContext>
            <local:ViewModel/>
        </Grid.DataContext>
        <ComboBox ItemsSource="{Binding ListOfPersons}"
                  SelectedItem="{Binding SelectedPerson}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</Window>

在运行时,我按照预期得到4个项目:1个空白菜单项,后跟3个非空白菜单项,Person集合中每个ViewModel.ListOfPersons一个,项目文本绑定到Name的{​​{1}}属性。

Image showing MainWindow view at run-time

我希望第一个空白项目代替显示文字“没有人”。我怎么能这样做?

我尝试过的一件事是使用以下数据转换器,它将Person引用转换为转换器参数中指定的对象:

null

然后我对视图进行了以下更改:

  1. 从上面添加namespace NoValueItem { public class NullSubstituteConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return value ?? parameter; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (parameter == null) return value; return parameter.Equals(value) ? null : value; } } } 作为静态资源。
  2. 添加了NullSubstituteConverter个对象作为静态资源来代表“无人”。项目并给了关键&#39; NullPerson&#39;。
  3. Person资源设置为转换器,用于绑定ComboBox的NullSubstituteConverter属性。
  4. SelectedItem资源设置为ComboBox的数据模板中的项目转换器,以便将项目源中的NullSubstituteConverter项目转换为null对象。“ / LI>

    这是更新后的视图:

    NullPerson

    这更接近我想要的。空白菜单项现在显示“没有人”,但仍有2个问题:

    1. 首次加载视图时,“无人”&#39;项目默认情况下不会自动选中。
    2. 无法选择“无人”&#39;项目
    3. Image showing MainWindow view at run-time after add data converter

      我欢迎任何有关如何获得“没有人”的建议。菜单项工作。它可以基于我上面的方法,或者只要它有效就完全不同的方法!

0 个答案:

没有答案