我是WPF数据绑定的初学者,我刚刚发现了一种令人困惑的行为。也许有人能帮我:
我的xaml代码将一个列表框绑定到一个列表:
<ListBox ItemsSource="{Binding Path=Axes}" SelectedItem="{Binding Path = SelectedAxis}" DisplayMemberPath = "Name" Name="listboxAxes"/>如果绑定到的实际项是一个列表,那么一切都会按预期进行。
但是,当我切换到KeyedCollection时,出现了一个更新问题。对NotifyPropertychanged("Axes")的调用不会作为一个整体更新ListBox。
对此有什么想法吗?
发布于 2009-06-09 20:19:24
如果正在收集的轴不是具有自己的Name属性的类,那么DisplayMemberPath=的“Name”属性可能会导致您看不到任何东西。
不过,将KeyedCollection用作ItemsSource是完全可以的。ItemsSource属性是ItemsControl.ItemsSource属性。它只要求它绑定到的任何东西都实现IEnumerable。
KeyedCollection实现了IEnumerable,因为它实现了集合。
下面是一个使用KeyedCollection的简短示例:
<Grid>
<DockPanel x:Name="QuickListButtonsStackPanel">
<Button DockPanel.Dock="Top"
Content="Load Animals"
Click="AnimalButtonClick" />
<Button DockPanel.Dock="Top"
Content="Load Objects"
Click="ObjectButtonClick" />
<TextBlock DockPanel.Dock="Bottom"
Background="Azure"
Text="{Binding SelectedExample}" />
<ListBox x:Name="uiListBox"
ItemsSource="{Binding Examples}"
SelectedItem="{Binding SelectedExample}" />
</DockPanel>
</Grid>我们的窗口和KeyedCollection的代码如下:
public partial class Window1 : Window, INotifyPropertyChanged
{
public Window1()
{
InitializeComponent();
this.DataContext = this;
}
public KeyedCollection<char, string> Examples
{
get;
set;
}
private string mySelectedExample;
public string SelectedExample
{
get
{ return this.mySelectedExample; }
set
{
this.mySelectedExample = value;
this.NotifyPropertyChanged("SelectedExample");
}
}
private void AnimalButtonClick(object sender, RoutedEventArgs e)
{
Examples = new AlphabetExampleCollection();
Examples.Add("Ardvark");
Examples.Add("Bat");
Examples.Add("Cat");
Examples.Add("Dingo");
Examples.Add("Emu");
NotifyPropertyChanged("Examples");
}
private void ObjectButtonClick(object sender, RoutedEventArgs e)
{
Examples = new AlphabetExampleCollection();
Examples.Add("Apple");
Examples.Add("Ball");
Examples.Add("Chair");
Examples.Add("Desk");
Examples.Add("Eee PC");
NotifyPropertyChanged("Examples");
}
#region INotifyPropertyChanged Members
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class AlphabetExampleCollection : KeyedCollection<char, string>
{
public AlphabetExampleCollection() : base() { }
protected override char GetKeyForItem(string item)
{
return Char.ToUpper(item[0]);
}
}可能会发生的另一个问题是,如果您只是在集合中添加/删除项,而不是重新设置集合。在上面的示例中,您可以看到我们正在重新恢复键值集合。如果我们不这样做,那么仅仅调用NotifyPropertyChanged什么也做不了。
我们再添加两个按钮来演示这一点:
<Button DockPanel.Dock="Top"
Content="Add Zebra"
Click="AddZebraClick" />
<Button DockPanel.Dock="Top"
Content="Add YoYo"
Click="AddYoYoClick" />还有汉德尔一家:
private void AddZebraClick(object sender, RoutedEventArgs e)
{
Examples.Add("Zebra");
NotifyPropertyChanged("Examples");
}
private void AddYoYoClick(object sender, RoutedEventArgs e)
{
Examples.Add("YoYo");
NotifyPropertyChanged("Examples");
}这两个都是因为不能在上工作。当您调用NotifyPropertyChanged时,必须实际更改该属性。在这种情况下,情况并非如此。我们已经修改了它的items,但是Examples集合仍然是同一个集合。为了解决这个问题,我们可以像在第一部分中一样循环集合,或者如果我们有权访问UI,我们可以调用:
uiListBox.Items.Refresh();我们也可以循环DataSource,我们可以循环列表框的ItemsSource,或者我们可以清除并重新分配绑定,但是仅仅调用UpdateTarget()并不能做到这一点。
发布于 2009-06-03 11:01:25
尝试调用listboxAxes.Items.Refresh()。这有时会有帮助。
发布于 2009-06-09 11:36:24
KeyedCollection既不实现INotifyCollectionChanged也不实现INotifyPropertyChanged。要让绑定自动更新自身,请使用实现这些接口的集合(例如ObservableCollection)。
https://stackoverflow.com/questions/943952
复制相似问题