我是WPF Databinding的初学者,我发现了一种令人困惑的行为。也许有人可以帮助我:
我的xaml代码将列表框绑定到列表:
<ListBox ItemsSource="{Binding Path=Axes}" SelectedItem="{Binding Path = SelectedAxis}" DisplayMemberPath = "Name" Name="listboxAxes"/>
如果绑定的实际项目是List,则一切都按预期工作。
但是当我改为KeyedCollection时会出现更新问题。调用NotifyPropertychanged(“Axes”)不会整体更新ListBox。
有关于此的任何想法吗?
答案 0 :(得分:4)
如果Axes正在收集的不是具有它自己的Name属性的类,那么DisplayMemberPath =“Name”属性可能会导致您看不到任何内容。
使用KeyedCollection作为ItemsSource是完全正常的。 ItemsSource属性是ItemsControl.ItemsSource属性。它只需要它实现IEnumerable所必需的任何东西。
KeyedCollection确实实现了IEnumerable,因为它实现了Collection。
以下是使用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>
我们的Window&amp;的代码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" />
Hanlders:
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时,必须实际更改该属性。在这种情况下,它不是。我们修改了它的项目,但Examples集合仍然是同一个集合。为了解决这个问题,我们可以像在第一部分中那样循环收集,或者如果我们可以访问UI,我们可以调用:
uiListBox.Items.Refresh();
我们也可以循环DataSource,我们可以循环ListBox的ItemsSource,或者我们可以清除并重新分配绑定,但只是调用UpdateTarget()不会这样做。
答案 1 :(得分:2)
尝试拨打listboxAxes.Items.Refresh()
。
这有时会有所帮助。
答案 2 :(得分:1)
KeyedCollection
既未实施INotifyCollectionChanged
也未实施INotifyPropertyChanged
。要使绑定自动更新,请使用实现这些接口的集合(例如ObservableCollection
)。
答案 3 :(得分:0)
WPF Gridview binding to a List of KeyedCollection objects.
Data binding to some index of Dictionary with "composite" key.
答案 4 :(得分:0)
将您的属性公开为IList类型的属性,并将ItemSource绑定到此属性:
public IList MyIListKeyedCollection { get { return myKeyedCollection; } }
并在myKeyedCollection发生变化时调用NotifyPropertyChanged(“MyIListKeyedCollection”)。我认为这应该有用......