【问题标题】:WPF How To Bind ComboBoxWPF如何绑定组合框
【发布时间】:2015-12-17 17:59:23
【问题描述】:

我正在尝试将我的 ComboBox 绑定到字符串列表,并且我希望它在加载 Window 后显示默认值。

为此,我创建了一个 ViewModel 类,例如:

namespace MyData
{
    class ViewModel
    {
        public ViewModel()
        {
            this.Name = "";
            this.Age = 0;
            this.Address = "";
            this.DateOfPurchase = DateTime.Now.AddDays(-30);
            this.CarModel = "VW"; //I want to set VW as default but options are Mazda, VW, Audi
        }

        public IEnumerable<String> CarModels
        {
            get
            {
                var carModels = new String[] {"Mazda", "VW", "Audi"};
                //CarModel = cars.FirstOrDefault(car => CarModel == "VW");  //this is not needed

                return carModels;
            }
        }

        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
        public DateTime DateOfPurchase { get; set; }
        public String CarModel { get; set; }
    }
}

然后我将 Window 的 DataSource 设置为我的 ViewModel

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    this.DataContext = new ViewModel();
}

最后,我想将我的控件绑定到这些数据。除了我的 ComboBox,我对所有其他人都这样做了。我希望它以模型(马自达、大众和奥迪)作为其 ComboBoxItems 的字符串数组,并默认为 2nd,即表单加载后的 VW。

然后我在我的 XAML 中像这样绑定它:

<ComboBox Name="cbCarModels" SelectedItem="{Binding CarModel, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding CarModels}">

这行得通!

【问题讨论】:

  • 仅供参考,如果它是字符串,您设置 Car = 的方式有效,但一旦项目不是字符串,它将不起作用。所选项目必须是项目源中的一个实例。注释掉的 // this is not required 实际上是更好的全方位方法。
  • 该项目将是字符串。它不应该被称为 Car 而是 CarModel。我会更新
  • @jeff 但是你介意解释一下吗?为什么我不能使用字符串。我知道,如果我希望我的下拉菜单包含像 Cars 这样的对象,在这种情况下,我可能不得不重写 toString 或我的 Car 类来显示我想要的。
  • 你可以使用字符串。那不是问题。随着您进入您的应用程序,您会发现绑定到对象而不是字符串更为常见。按照您的示例,说 Car 不是字符串,而是具有更多属性的对象。然后您将绑定到 Car.Name
  • fwiw...如果你覆盖 ToString,你做错了,你还没有得到 wpf 范式。

标签: c# wpf xaml


【解决方案1】:

想不通

在 xaml 中

<Combobox ItemsSource="{Binding Path=CarModels}", SelectedItem="{Binding SelectedCar}/>

您需要创建 ViewModel.SelectedCar 模型。在 vm.ctor 中设置

this.SelectedCar = Cars[1]

您可能必须将Path=CarModels, Mode=TwoWay 添加到绑定中。

【讨论】:

  • 我已经想通了,但感谢杰夫。我更新了我的问题。现在就是答案。
【解决方案2】:

此外,绑定到复杂对象有时更方便(例如,在编辑现有对象的属性时)。为此,您可以按照您的建议覆盖此对象的 ToString() 方法,但您也可以通过 DisplayMemberPath 属性将组合框项中显示的值绑定到 XAML 中该对象的特定成员:

<ComboBox ItemsSource="{Binding CarModel}" DisplayMemberPath="Name" SelectedItem="{Binding CarModels}" />

这样做的好处是您可以将这个额外的ToString() 代码保留在您的 POCO 之外。

【讨论】:

    【解决方案3】:

    如果您打算利用带有 WPF(或任何基于 XAML 的语言)的 MVVM,请了解 DataBinding 引擎与 INotifyPropertyChanged 接口的大量工作。用户界面订阅PropertyChanged事件,并根据绑定更新UI控件。

    这是一个示例,仅包含相关部分。请注意,我不包括 INPC 的实现,但是有许多框架提供了抽象基类,如果您不想走那条路,那里有很多资源描述了如何实现 INPC 接口。

    MyViewModel.cs:

    public class MyViewModel : INotifyPropertyChanged
    {
        public MyViewModel()
        {
            CarModels = new[] {"Mazda", "VW", "Audi"};
            SelectedCarModel = "VW";
        }
    
        public IEnumerable<string> CarModels { get; private set; }
    
        private string _selectedCarModel;
        public string SelectCarModel
        {
            get { return _selectedCarModel; }
            set
            {
                if (_selectedCarModel == value) return;
    
                _selectedCarModel = value;
                OnPropertyChanged("SelectedCarModel");
            }
        }
    }
    

    XAML:

    <ComboBox ItemsSource="{Binding Path=CarModels, Mode=OneTime}"
              SelectedItem="{Binding Path=SelectedCarModel}" />
    

    简单地说,如果你实现了 INPC 并引发了一个属性更改通知,DataBinding 引擎将根据属性的名称调用属性获取方法。然后它将更新必要的 UI 控件。此外,用户界面也会更新视图模型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-18
      • 2011-03-09
      • 1970-01-01
      • 2012-11-12
      • 2015-09-15
      相关资源
      最近更新 更多