2009-06-03 9 views
1

Je suis un débutant de la liaison de données WPF et je viens de trouver un type de comportement confus. Peut-être quelqu'un peut me aider:DataBinding wpf KeyedCollection

Mon code XAML lie une zone de liste à une liste:

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

Si l'élément réel qui est lié à un est tout Liste fonctionne comme prévu. Mais quand je passe à KeyedCollection, il y a un problème de mise à jour. Les appels à NotifyPropertychanged ("Axes") ne met PAS à jour le ListBox dans son ensemble.

Des idées à ce sujet?

+0

vous devez marquer le code XAML comme du code ou il n'apparaît pas dans votre question. –

Répondre

4

Si tout Haches collecte est pas une classe avec son propre nom propriété, alors la propriété DisplayMemberPath = « Nom » peut vous causer de ne pas voir quoi que ce soit. L'utilisation d'une KeyedCollection en tant que ItemsSource est cependant parfaitement satisfaisante. La propriété ItemsSource est la propriété ItemsControl.ItemsSource. Et il exige simplement que tout ce qu'il est obligé d'implémenter IEnumerable.

KeyedCollection met en œuvre IEnumerable, car il implémente Collection.

est un exemple simple en utilisant un 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> 

Et le code de notre fenêtre & 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]); 
    } 
} 

L'autre question qui peut se produire est si vous êtes l'ajout/suppression éléments de la collection, et ne pas redéfinir la collection. Dans l'exemple ci-dessus, vous pouvez voir que nous réinstallons la collection de clés. Si nous ne l'avons pas fait, appeler simplement NotifyPropertyChanged ne ferait rien.

permet d'ajouter deux autres boutons pour démontrer:

<Button DockPanel.Dock="Top" 
     Content="Add Zebra" 
     Click="AddZebraClick" /> 
<Button DockPanel.Dock="Top" 
     Content="Add YoYo" 
     Click="AddYoYoClick" /> 

Et les 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"); 
} 

ces deux, comme cela est ne fonctionnera pas. Lorsque vous appelez NotifyPropertyChanged, la propriété doit être modifiée. Et dans ce cas, ce n'est pas le cas. Nous avons modifié ses éléments, mais la collection Exemples est toujours la même collection.Pour résoudre ce problème, nous le cycle pourrait la collection comme nous l'avons fait dans la première partie, ou si nous avons accès à l'interface utilisateur, nous pourrions appeler:

uiListBox.Items.Refresh(); 

On pourrait aussi du vélo le DataSource, nous pourrions le cycle ItemsSource de la zone de liste, ou nous pourrions effacer et réaffecter la liaison, mais en appelant simplement UpdateTarget() ne le fera pas cependant.

2

Essayez d'appeler listboxAxes.Items.Refresh(). Ça aide parfois.

+0

Cela fonctionnera probablement. Mais nous ne voulons pas ajouter de code. Cela devrait fonctionner par défaut par la mécanique de liaison. – Matze

+0

Je n'ai aucune expérience liée à un KeyedCollection. Donc j'espère que quelqu'un d'autre est capable de t'aider. –

2

KeyedCollection n'implémente pas non plus INotifyCollectionChanged ni INotifyPropertyChanged. Pour que la liaison se mette automatiquement à jour, utilisez une collection qui implémente ces interfaces (ObservableCollection par exemple).

+0

Il ne s'agit PAS des éléments de KeyCollection ... Il s'agit d'un nouvel objet KeyCollection complet. Sa modification est notifiée correctement par un événement NotifyPropertyChanged (..). – Matze

0

Exposez votre propriété comme une propriété IList typé, et lier la ItemSource à cette propriété:

public IList MyIListKeyedCollection { get { return myKeyedCollection; } } 

et faire l'appel NotifyPropertyChanged (« MyIListKeyedCollection ») lorsque la chaque fois que les changements de myKeyedCollection. Je pense que cela devrait fonctionner ...