2009-06-03 54 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變化時。我認爲這應該工作...