Question

Ive a remarqué ce deux ou trois fois lors de l'utilisation des menus avec des commandes, ils ne sont pas très dynamiques, vérifier cela. Je crée un menu à partir d'une collection de couleurs, je l'utilise pour colorer une colonne dans une grille de données. Quoi qu'il en soit quand j'ai afficher le menu (son un menu contextuel), le paramètre de commande de liaison qui se passe et il se lie à la colonne que le menu contextuel a été ouvert sur. Cependant, la prochaine fois que je la mettre il semble WPF met en cache le menu et il ne marche pas redéfinissez le paramètre de commande. donc je peux définir la couleur que sur la colonne initiale que le menu contextuel est apparu sur.

J'ai eu le temps de cette situation dans le passé en faisant le menu tout à fait dynamique et la destruction de la collection lorsque le menu fermé et en forçant une recréation la prochaine fois qu'il a ouvert, je ne aime pas ce hack. Quelqu'un at-il une façon meilleure?

    <MenuItem
       Header="Colour"
       ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColumnColourCollection}"
       ItemTemplate="{StaticResource colourHeader}" >
       <MenuItem.Icon>
          <Image
             Source="{StaticResource ColumnShowIcon16}" />
       </MenuItem.Icon>
       <MenuItem.ItemContainerStyle>
          <Style
             TargetType="MenuItem"
             BasedOn="{StaticResource systemMenuItemStyle}">
             <!--Warning dont change the order of the following two setters
                                otherwise the command parameter gets set after the command fires,
                                not mush use eh?-->
             <Setter
                Property="CommandParameter">
                <Setter.Value>
                   <MultiBinding>
                      <MultiBinding.Converter>
                         <local:ColumnAndColourMultiConverter/>
                      </MultiBinding.Converter>
                      <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridColumnHeader}}" Path="Column"/>
                      <Binding Path="."/>
                   </MultiBinding>
                </Setter.Value>
             </Setter>
             <Setter
                Property="Command"
                Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColourColumnCommand}" />
          </Style>
       </MenuItem.ItemContainerStyle>
    </MenuItem>
Était-ce utile?

La solution

Le problème est que ce sont ContextMenu apparemment la racine de leur propre arbre visuel Je lis quelque part que cela prend DataContext sa parent, mais une seule fois sur le chargement, donc si les parents datacontext changements les menuitems ne fonctionne pas. (Malheureusement je ne peux pas trouver un lien pour ce droit non)

J'ai rencontré ce problème avant, et ce que je faisais était l'utilisation Modèle de branche virtuel Josh Smith . Il est assez technique, mais l'article m'a aidé à comprendre très bien ce qui se passait avec ce non-sens de l'arbre visuel.

Pour l'essentiel, vous créez ce pont qui se fixe à la datacontext de la vue. Le pont est créé en tant que ressource statique , vous permettant de lier à partir du menu contextuel même si elle est en dehors de l'arbre visuel.

Ajouter à votre XAML:

<Window.Resources>
   <!-- This is the "root node" in the virtual branch
   attached to the logical tree. It has its
   DataContext set by the Binding applied to the
   Window's DataContext property. -->
   <FrameworkElement x:Key="DataContextBridge" />
</Window.Resources>

<Window.DataContext>
   <!-- This Binding sets the DataContext on the "root node"
   of the virtual logical tree branch.  This Binding
   must be applied to the DataContext of the element
   which is actually assigned the data context value. -->
   <Binding
    Mode="OneWayToSource"
    Path="DataContext"
    Source="{StaticResource DataContextBridge}"
   />
</Window.DataContext>

est le pont dont je parlais. Il prend la datacontext et it_ __pushes pour les ponts DataContext, qui est (comme je l'ai déjà dit) une ressource statique.

Ensuite, vous simplement ceci à la datacontext du contextmenu:

 DataContext="{Binding
               Source={StaticResource DataContextBridge},
               Path=DataContext}"

Maintenant jeter tous les etc pathing relative et liant l'utilisation régulière à l'intérieur des éléments de menu, et vous devriez être bien. Le datacontext mettra à jour comme d'habitude.

Juste une remarque:

Vous devrez évidemment avoir une propriété dans le datacontext de discerner ce qui commande à utiliser, mais je suis sûr que vous pouvez comprendre. Cette solution traite seulement avec la mise à jour de Do not la façon dont contextmenu

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top