DropDownOpened事件上设置的WPF组合框绑定列表

本文关键字:组合 绑定 列表 WPF 事件 设置 DropDownOpened | 更新日期: 2023-09-27 18:26:43

我的问题是ComboBox没有显示存储在其绑定列表中的值。

以下是我正在做的:

WPF:

<ComboBox ItemsSource="{Binding Devices}" 
  DropDownOpened="deviceSelector_DropDownOpened"/>

注意,我的WindowDataContext{Binding RelativeSource={RelativeSource Self}}

C#代码背后:

public List<String> Devices { get; set; }
private void deviceSelector_DropDownOpened(object sender, EventArgs e)
{
  // the actual population of the list is occuring in another method 
  // as a result of a database query. I've confirmed that this query is
  // working properly and Devices is being populated.
  var dev = new List<String>();
  dev.Add("Device 1");
  dev.Add("Device 2");
  Devices = dev;
} 

我尝试过用ObservableCollection而不是List来实现这一点,我也尝试过使用PropertyChangedEventHandler。这两种方法对我都不起作用

知道为什么当我点击下拉列表时我的项目没有显示吗?

DropDownOpened事件上设置的WPF组合框绑定列表

既然您是在代码隐藏中完成这项工作的,为什么不直接设置ComboBox.ItemsSource呢。

现在,我不会说这是应该在WPF中的方式(我更希望视图的数据加载在ViewModel中),但它会解决您的问题。

这不起作用的原因是您的属性在更改时不会通知绑定系统。我知道你说过你用PropertyChangedEventHandler试过了,但除非你的View看起来像这样,否则这是行不通的:

public class MyView : UserControl, INotifyPropertyChanged
{
    private List<String> devices;
    public event PropertyChangedEventHandler PropertyChanged;
    public List<String> Devices
    {
        get { return devices; }
        set 
        {
            devices = value;
            // add appropriate event raising pattern
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Devices"));
        }
    }
    ...
}

同样,使用ObservableCollection只能像这样工作:

private readonly ObservableCollection<string> devices = new ObservableCollection<string>();
public IEnumerable<string> Devices { get { return devices; } }
private void deviceSelector_DropDownOpened(object sender, EventArgs e)
{
    devices.Clear();
    devices.Add("Device 1");
    devices.Add("Device 2");
} 

任何一种方法都应该填充ComboBox,在我刚刚运行的一个快速测试中,它起了作用。

编辑以添加DependencyProperty方法

最后一种方法是使用DependencyProperty(因为您的ViewDependencyObject:

public class MyView : UserControl
{
    public static readonly DependencyProperty DevicesProperty = DependencyProperty.Register(
      "Devices",
      typeof(List<string>),
      typeof(MainWindow),
      new FrameworkPropertyMetadata(null));
    public List<string> Devices
    {
        get { return (List<string>)GetValue(DevicesProperty); }
        set { SetValue(DevicesProperty, value); }
    }
    ...
}

下面的更改(由Abe Heidebrecht建议)解决了这个问题,但我不知道为什么。有人愿意解释一下吗?

WPF:

<ComboBox DropDownOpened="deviceSelector_DropDownOpened"
  Name="deviceSelector"/>

C#代码背后:

private void deviceSelector_DropDownOpened(object sender, EventArgs e)
{
  var dev = new List<String>();
  dev.Add("Device 1");
  dev.Add("Device 2");
  deviceSelector.ItemsSource = dev;
} 

除非我在这里遗漏了什么:

当更新设备属性的设备时,尝试激发OnPropertyChanged,这应该可以解决此问题。我偶尔也不得不设置模式:

ItemsSource="{Binding Devices, Mode=TwoWay}"

在某些控件上。

直接在控件上设置项源告诉控件直接使用新项,而不使用xaml中连接的绑定。更新datacontext上的Devices属性不会告诉组合框Devices属性已更改,因此不会更新。通知组合框更改的方法是在设备属性更改时为其激发OnPropertyChanged。