在DropDownOpened事件上设置WPF ComboBox绑定列表

时间:2013-08-07 19:02:39

标签: c# wpf binding combobox

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

以下是我正在做的事情:

WPF:

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

请注意,我的Window DataContext{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。这些方法都没有对我有用。

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

3 个答案:

答案 0 :(得分:3)

由于您无论如何都要在代码中执行此操作,为什么不直接设置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); }
    }

    ...
}

答案 1 :(得分:0)

以下变化(由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;
} 

答案 2 :(得分:0)

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

尝试在设备更新设备属性时触发OnPropertyChanged,这应解决此问题。我偶尔也必须设置模式:

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

在一些控件上。

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