2009-06-03 73 views
1

我是WPF Databinding的初学者,我刚刚发现了一种令人困惑的行为。也许有人可以帮助我:DataBinding wpf KeyedCollection

我的XAML代码绑定列表框列表:

<ListBox ItemsSource="{Binding Path=Axes}" SelectedItem="{Binding Path = SelectedAxis}" DisplayMemberPath = "Name" Name="listboxAxes"/> 

如果绑定到实际的产品的清单一切正常。

但是,当我改变到KeyedCollection出现更新问题。对NotifyPropertychanged(“Axes”)的调用不会整体更新ListBox。

对此的任何想法?

+0

您需要将XAML代码标记为代码或它不会显示在您的问题中。 – 2009-06-03 10:49:42

回答

4

如果任何轴正在收集不与它自己的名称属性,然后一类的DisplayMemberPath =“名称”属性可能会导致你看不到任何东西。

虽然使用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> 

并为我们的窗口& 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(); 

我们也可以循环的数据源,我们可以循环ListBox的ItemsSource时,或者我们可以清除并重新分配绑定,但只是调用UpdateTarget()不会这样做。

2

尝试拨打listboxAxes.Items.Refresh()。 有时会有所帮助。

+0

这可能会起作用。但我们不想添加代码。它应该只是默认绑定机制。 – Matze 2009-06-03 11:15:47

+0

我没有任何绑定到KeyedCollection的经验。所以我希望别人能够帮助你。 – 2009-06-03 11:24:57

2

KeyedCollection既没有实施INotifyCollectionChanged也没有实施INotifyPropertyChanged。要使绑定自动更新,请使用实现这些接口的集合(例如ObservableCollection)。

0

暴露你的财产作为一个IList类型的属性和绑定的ItemSource这个属性:

public IList MyIListKeyedCollection { get { return myKeyedCollection; } } 

,并做了呼叫NotifyPropertyChanged(“MyIListKeyedCollection”)的每当myKeyedCollection变化时。我认为这应该工作...