2017-03-22 2 views
3

Dans le suivant WPF ListView, j'ai créé deux ContextMenus: Un pour le ListView lui-même et un à utiliser pour chaque élément de liste spécifique. Il ressemble un peu à ceci:Comment créer des blocs de code XAML réutilisables, indépendants du contexte?

<ListView ItemsSource="{Binding Path=MyListData}"> 
    <ListView.ContextMenu> 
     <ContextMenu> <!-- menu for the entire list --> 
      <MenuItem Header="New Item"/> 
      <MenuItem Header="Sort by"> 
       <MenuItem Header="Name"/> 
       <MenuItem Header="Author"/> 
       <MenuItem Header="Date"/> 
      </MenuItem> 
     </ContextMenu> 
    </ListView.ContextMenu> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="{x:Type ListViewItem}"> 
      <Setter Property="ContextMenu"> 
       <Setter.Value> 
        <ContextMenu> <!-- menu for a specific item --> 
         <MenuItem Header="Edit"/> 
         <MenuItem Header="Remove"/> 
         <Separator/> <!-- note how the following is basically the same as the other menu --> 
         <MenuItem Header="New Item"/> 
         <MenuItem Header="Sort by"> 
          <MenuItem Header="Name"/> 
          <MenuItem Header="Author"/> 
          <MenuItem Header="Date"/> 
         </MenuItem> 
        </ContextMenu> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ListView.ItemContainerStyle> 
    <ListView.View> 
     <!-- ListView content --> 
    </ListView.View> 
</ListView> 

Cela fonctionne, mais comme vous pouvez le voir, le premier contenu de est réutilisé comme Menu contextuel partie de la deuxième. En effet, je souhaite que les options générales (Nouvel élément/Trier par) soient également disponibles lorsque l'utilisateur clique avec le bouton droit sur un élément plutôt que sur un espace vide. Puisque je prévois d'utiliser cette structure générale plus d'une fois, je peux m'imaginer que cela devient plutôt compliqué, surtout quand toutes les liaisons de commandes nécessaires sont prises en compte.

J'ai essayé de définir un DataTemplate dans <ListView.Resources> comme expliqué dans les réponses à des questions similaires, mais cela ne fonctionne pas parce que Apperently autonome MenuItem s ne peuvent pas être enveloppés dans un modèle. Et si j'insère les balises <ContextMenu> dans le modèle, il existe une exception d'exécution, car un ContextMenu ne peut pas habiter dans un autre ContextMenu.

Est-il possible de créer des extraits de code réutilisables qui nécessiteraient normalement des éléments parents spécifiques? Une sorte de modèle qui a été évalué au moment de la compilation? Tout ce que je veux, c'est un code plus facile à maintenir.

Répondre

2

Vous pouvez le faire comme ceci:

<Window.Resources> 
    <MenuItem x:Key="newItem" Header="New Item" Command="{x:Static ApplicationCommands.New}" x:Shared="False" /> 
    <MenuItem x:Key="sortBy" Header="Sort by" x:Shared="False"> 
     <MenuItem Header="Name" Click="SortByNameClicked"/> 
     <MenuItem Header="Author"/> 
     <MenuItem Header="Date"/> 
    </MenuItem> 
</Window.Resources> 
<ListView ItemsSource="{Binding Path=MyListData}"> 
    <ListView.ContextMenu> 
     <ContextMenu> 
      <!-- menu for the entire list --> 
      <StaticResource ResourceKey="newItem" /> 
      <StaticResource ResourceKey="sortBy" /> 
     </ContextMenu> 
    </ListView.ContextMenu> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="{x:Type ListViewItem}"> 
      <Setter Property="ContextMenu"> 
       <Setter.Value> 
        <ContextMenu> 
         <!-- menu for a specific item --> 
         <MenuItem Header="Edit"/> 
         <MenuItem Header="Remove"/> 
         <Separator/> 
         <StaticResource ResourceKey="newItem" /> 
         <StaticResource ResourceKey="sortBy" /> 
        </ContextMenu> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ListView.ItemContainerStyle> 
</ListView> 

Remarque x:Shared="false" attribut. Ce qu'il fait, c'est faire référence à cette ressource pour créer une nouvelle copie. Par défaut, la même instance de ressource est réutilisée, mais cela ne correspond pas à notre scénario, car nous avons besoin de différentes instances pour des menus différents (sinon, il se plaindra que le même élément ne peut pas être des enfants de plusieurs parents).

Vous pouvez définir des liaisons de commandes et cliquer sur des événements (comme vous le voyez) comme d'habitude sur ces éléments.