2010-12-14 89 views
0

J'essaie de lier le menu contextuel (avec case à cocher) de tabulation à la collection observable. Lorsque l'utilisateur vérifie ou supprime le menuitem pour la première fois, cet état est reflété dans variable bool associée dans la collection obesarvable. Mais après ça, ça ne s'est pas reflété. Reliure en XAML ressemble à ceci:WPF Menu contextuel Liaison de données

 <TabItem.ContextMenu> 
      <ContextMenu Name="menu" 
         ItemsSource="{Binding Path=FieldNameCollection,Mode=TwoWay}" 
         ItemTemplate="{StaticResource SelectIndexFieldMenu}"></ContextMenu> 
     </TabItem.ContextMenu> 

Modèle de données est

 <DataTemplate x:Key="SelectIndexFieldMenu"> 
      <MenuItem Header="{Binding Path=IndexFieldName}" 
         IsCheckable="True" 
         IsChecked="{Binding Path=isIndexFieldSelected,Mode=TwoWay}" 
         IsEnabled="{Binding Path=isCheckBoxEnabled}" /> 
     </DataTemplate> 

(je ne suis pas en mesure d'ajouter l'extrait de code, alors j'ai enlevé '<' :() La classe de collection observable Une autre chose que j'ai remarquée est que si je vérifie la source d'éléments du menu contextuel dans view.xaml.cs à ContextMenuClosing, les états sont correctement reflétés

+0

Implémentez-vous l'interface 'INotifyPropertyChanged' dans votre classe? – decyclone

+0

Oui, j'ai implémenté INotifyProperyChanged. Thx pour ajouter du code correctement (comment avez-vous fait cela?) – Rik

+0

s'il vous plaît coller le code pertinent du présentateur aussi, et si possible, coller aussi une plus grande partie de votre xaml. Je suis ce que DataContext TabControl.so collez le xaml TabControl. – Nawaz

Répondre

0

Ce n'est pas c apprenez sans voir plus de code ce qui cause les propriétés à ne pas mettre à jour mais il y a quelques problèmes qui peuvent contribuer.

Les valeurs "isIndexFieldSelected" et "isCheckBoxEnabled" ressemblent à des noms de champ plutôt qu'à des propriétés. Si c'est le cas qui causerait le problème puisque Binding requiert des propriétés mais vu le code affiché, ce n'est pas clair.

La façon dont vous modélisez les éléments de menu entraîne la création de deux objets MenuItem pour chaque élément de collection. ContextMenu génère automatiquement une instance MenuItem pour chaque élément de la collection ItemsSource liée dans laquelle le DataTemplate de chaque élément est injecté. En déclarant un MenuItem dans le ItemTemplate vous créez un MenuItem dans la section Header de chaque MenuItem dans le ContextMenu. Il se peut que vous cliquiez sur, et que vous vérifiiez, le MenuItem externe qui n'est pas lié aux données. Essayez d'utiliser ces ressources à la place à la fois modèle et le style des MenuItems qui sont générés pour vous:

<DataTemplate x:Key="SelectIndexFieldMenuTemplate"> 
    <TextBlock Text="{Binding Path=IndexFieldName}"/> 
</DataTemplate> 

<Style x:Key="SelectIndexFieldMenuStyle" TargetType="{x:Type MenuItem}"> 
    <Setter Property="IsCheckable" Value="True" /> 
    <!--IsChecked is already TwoWay by default--> 
    <Setter Property="IsChecked" Value="{Binding Path=isIndexFieldSelected}" /> 
    <Setter Property="IsEnabled" Value="{Binding Path=isCheckBoxEnabled}" /> 
</Style> 

et de les utiliser comme ceci:

<TabItem.ContextMenu> 
    <!--TwoWay doesn't ever do anything on ItemsSource--> 
    <ContextMenu Name="menu" ItemsSource="{Binding Path=FieldNameCollection}" 
       ItemContainerStyle="{StaticResource SelectIndexFieldMenuStyle}" 
       ItemTemplate="{StaticResource SelectIndexFieldMenuTemplate}"/> 
</TabItem.ContextMenu> 

Il est également possible que vos propriétés liées n'utilisent pas correctement INotifyPropertyChanged , ce qui empêcherait l'interface utilisateur de se mettre à jour lorsque l'élément de menu vérifiait l'état. Cela devrait ressembler à ceci:

private bool _isIndexFieldSelected; 
public bool isIndexFieldSelected 
{ 
    get { return _isIndexFieldSelected; } 
    set 
    { 
     if (_isIndexFieldSelected == value) 
      return; 
     _isIndexFieldSelected = value; 
     NotifyPropertyChanged("isIndexFieldSelected"); 
    } 
} 

public virtual void NotifyPropertyChanged(string propertyName) 
{ 
    PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName); 
    if (PropertyChanged != null) 
     PropertyChanged(this, ea); 
} 

public event PropertyChangedEventHandler PropertyChanged; 
+0

Thx John pour votre réponse. Toutes ces varibales sont des properies implémentant INotifyPropertyChange. J'ai finalement réalisé cela en utilisant ContextMenu.Resources (à droite, plus tôt, il générait deux menus (menu avec dans le menu)) et lire les propriétés directement à partir de la source de l'élément du menu. Je ne sais pas si c'est la bonne façon de le faire, mais ça marche. – Rik