我试图将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,并且没有可用于绑定的路径。
我真诚地希望我没有做出一些愚蠢的拼写错误(我已经复制/粘贴了一些我没有运气就能找到的命名空间);不过,我绝对会失败。
答案 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上绑定到DataContext
到RelativeSource 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" ));
}
}
。