2017-03-22 1 views
3

In der folgenden WPF ListView, erstellte ich zwei ContextMenus: Eine für die ListView selbst und eine für jedes spezifische Listenelement verwendet werden. Es sieht ein bisschen wie folgt aus:Wie erstellt man wiederverwendbare, kontextunabhängige XAML-Codebausteine?

<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> 

Dies funktioniert, aber wie Sie sehen können, das erste contextMenu Inhalt wird als Teil des zweiten wiederverwendet werden. Dies liegt daran, dass die allgemeinen Optionen (Neues Element/Sortieren nach) auch verfügbar sein sollen, wenn der Benutzer mit der rechten Maustaste auf ein Element und nicht auf einen leeren Bereich klickt. Da ich plane, diese allgemeine Struktur mehr als einmal zu verwenden, kann ich mir vorstellen, dass dies ziemlich unordentlich wird, besonders wenn alle notwendigen Befehlsbindungen berücksichtigt werden.

Ich versuchte, ein DataTemplate in <ListView.Resources> definieren, wie in Antworten auf ähnliche Fragen erklärt, aber das wird nicht funktionieren, weil apperently MenuItem s Standalone kann nicht in einer Vorlage eingewickelt werden. Und wenn ich die <ContextMenu> Tags in die Vorlage einfügen, gibt es eine Laufzeitausnahme, weil ein ContextMenu nicht in einem anderen ContextMenu leben kann.

Gibt es eine Möglichkeit, wiederverwendbare Code-Snippets zu erstellen, die normalerweise bestimmte Elternelemente benötigen? Eine Art von Vorlage, die zur Kompilierzeit ausgewertet wird? Alles was ich will, ist mehr wartbarer Code.

Antwort

2

Sie können es wie folgt tun:

<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> 

Hinweis x:Shared="false" Attribut. Was es tut, macht jeden Verweis auf diese Ressource, um eine neue Kopie zu erstellen. Standardmäßig wird die gleiche Instanz der Ressource wiederverwendet, aber das passt nicht zu unserem Szenario, da wir für verschiedene Menüs unterschiedliche Instanzen benötigen (andernfalls wird es sich beschweren, dass dasselbe Element nicht untergeordnete Elemente sein kann).

Sie können Befehlsbindungen und Klickereignisse (wie Sie sehen) wie üblich auf solchen Elementen definieren.

Verwandte Themen