将ObservableCollection绑定到ComboBox

时间:2014-03-12 17:09:07

标签: c# wpf xaml data-binding combobox

我试图将ObservableCollection(C#)绑定到ComboBox(XAML)。互联网上的一百万篇文章,问题/答案以及帖子都表明这是一项非常简单的任务。到目前为止,我不得不反对他们:

XAML

<Window
    x:Class     = "ComboTest.MainWindow"
    xmlns       = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x     = "http://schemas.microsoft.com/winfx/2006/xaml"
    Title       = "MainWindow"
    Height      = "350"
    Width       = "525"
    DataContext = "{Binding RelativeSource={RelativeSource Self}}">
    <StackPanel>
        <ComboBox 
            Name          = "URICombo"
            ItemsSource   = "{Binding URIs}" 
            SelectedIndex = "0">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"></TextBlock>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

C#

namespace ComboTest
{
    public partial class MainWindow : Window
    {
        public class URIPairing
        {
            public string URI  { get; set; }
            public string Name { get; set; }

            public URIPairing(string _Name, string _URI)
            {
                this.Name = _Name;
                this.URI  = _URI;
            }
        }

        public ObservableCollection<URIPairing> URIs { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            this.URIs = new System.Collections.ObjectModel.ObservableCollection<URIPairing>();
            this.URIs.Add(new URIPairing( "DEV"     , "Some URL" ));
            this.URIs.Add(new URIPairing( "SANDBOX" , "Some URL" ));
            this.URIs.Add(new URIPairing( "QA"      , "Some URI" ));
        }
    }
}

运行时,应用程序会显示一个简单的空ComboBox。

调试显示ObservableCollection填充正确,并查看Visual Studio&#34;应用数据绑定...&#34;面板,我可以看到DataContext为null,并且没有可用于绑定的路径。

Apply Data Binding dialog box

我真诚地希望我没有做出一些愚蠢的拼写错误(我已经复制/粘贴了一些我没有运气就能找到的命名空间);不过,我绝对会失败。

3 个答案:

答案 0 :(得分:3)

您忘了将DataContext设置为自己:

public MainWindow()
{
   InitializeComponent();
   DataContext = this;
}

可能在XAML中:

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}"/>

当然你的组合框声明应该是这样的:

<ComboBox ItemsSource="{Binding URIs}"/>

更新(对于未来偶然发现这篇文章的人)

通常使用ViewModels完成绑定,因此我觉得任何UI组件都不应该实现INPC。但是,这完全是基于意见的。

无论如何,如果你从XAML设置DataContext,它就无法正常工作,因为XAML会被行InitializeComponent()解析,但是那时列表没有被初始化,所以绑定失败了(你可以检查一下) VS2010的输出窗口,你会看到那边的绑定失败消息。

话虽如此,如果您希望它也可以在XAML中工作(不使用INPC),您只需在InitializeComponent()之前初始化列表,它将在双方都有效。

    public MainWindow()
    {
        URIs = new ObservableCollection<URIPairing>();
        InitializeComponent();

        this.URIs.Add(new URIPairing("DEV", "Some URL"));
        this.URIs.Add(new URIPairing("SANDBOX", "Some URL"));
        this.URIs.Add(new URIPairing("QA", "Some URI"));
    }

答案 1 :(得分:1)

您错过了分配给组合框的主要部分。

        this.URIs = new stem.Collections.ObjectModel.ObservableCollection<URIPairing>();
         this.URIs.Add(new URIPairing("DEV", "Some URL"));
        this.URIs.Add(new URIPairing("SANDBOX", "Some URL"));
        this.URIs.Add(new URIPairing("QA", "Some URI"));
        URICombo.ItemsSource = URIs;
        URICombo.DisplayMemberPath = "Name";

答案 2 :(得分:1)

无效的原因是您的INotifyPropertyChanged未实施MainWindow。当您在Window上绑定到DataContextRelativeSource Self时,最初在运行应用程序时,它尝试获取尚未设置的URIs属性,然后重置{在DataContext的构造函数中{1}}将其标记为新的并且已经很晚,因此您需要调用this

一个简单而简洁的解决方法是删除构造函数中INPC的设置或DataContext中的绑定,但不能同时删除。

XAML

这会将新值传播到public partial class MainWindow : Window, INotifyPropertyChanged { // Implementation of the INPC protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } public class URIPairing { public string URI { get; set; } public string Name { get; set; } public URIPairing(string _Name, string _URI) { this.Name = _Name; this.URI = _URI; } } private ObservableCollection<URIPairing> _uris; public ObservableCollection<URIPairing> URIs { get { return _uris; } set { _uris = value; OnPropertyChanged(); } } public MainWindow() { InitializeComponent(); DataContext = this; this.URIs = new System.Collections.ObjectModel.ObservableCollection<URIPairing>(); this.URIs.Add(new URIPairing( "DEV" , "Some URL" )); this.URIs.Add(new URIPairing( "SANDBOX" , "Some URL" )); this.URIs.Add(new URIPairing( "QA" , "Some URI" )); } }