2009-06-03 6 views
1

Я начинаю работать с WPF Databinding, и я просто нашел запутанное поведение. Может быть, кто-то может помочь мне:DataBinding wpf KeyedCollection

Мой XAML код связывает ListBox в список:

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

Если фактический элемент, который связан является список все работает, как ожидалось.

Но когда я перехожу к KeyedCollection, возникает проблема с обновлением. Вызовы NotifyPropertychanged («Оси») НЕ обновляют ListBox в целом.

Любые идеи об этом?

+0

вам нужно пометить код XAML как код или он не отображается в вашем вопросе. –

ответ

4

Если все, что топоры собирает не класс с его собственного имени собственности тогда = свойство «Name» 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, свойство должно быть действительно изменено. И в этом случае это не так. Мы изменили его элементы, но коллекция примеров по-прежнему остается той же коллекцией.Чтобы исправить это, мы могли бы цикл сбора, как мы это делали в первой части, или если мы имеем доступ к пользовательскому интерфейсу, мы могли бы назвать:

uiListBox.Items.Refresh(); 

Мы могли бы также цикл источника данных, мы могли бы цикл в ListBox в ItemsSource, или мы могли бы очистить и повторно назначить привязку, но просто вызов UpdateTarget() не будет делать этого.

2

Попробуйте позвонить listboxAxes.Items.Refresh(). Это иногда помогает.

+0

Это будет работать. Но мы не хотим добавлять код. Он должен работать только по умолчанию, связывая механику. – Matze

+0

У меня нет привязки к ключу KeyedCollection. Поэтому я надеюсь, что кто-то еще поможет вам. –

2

KeyedCollection не реализует ни INotifyCollectionChanged, ни INotifyPropertyChanged. Чтобы привязка автоматически обновлялась, используйте коллекцию, которая реализует эти интерфейсы (например, ObservableCollection).

+0

Это не о элементах KeyCollection ... Речь идет о полном новом объекте KeyCollection. Это изменение уведомляется должным образом событием NotifyPropertyChanged (..). – Matze

0

Expose вашей собственности как IList типизированной собственность, и связать ItemSource этого свойства:

public IList MyIListKeyedCollection { get { return myKeyedCollection; } } 

и сделать вызов NotifyPropertyChanged («MyIListKeyedCollection») при каждом изменении в myKeyedCollection. Я думаю, что это должно сработать ...