9

Gibt es eine Möglichkeit, in einem TreeViewHierarchicalDataTemplate eine andere ContextMenu abhängig von einer Eigenschaft auf die Daten, an die ein Element gebunden ist, zu verwenden?Ändern des Kontextmenüs in WPF TreeView für Daten

Zum Beispiel Anzeige eines ContextMenu wenn Item.IsFile wahr ist, ein anderes an, wenn Item.IsFolder wahr ist, usw.

Antwort

13

Dies ist Beispiel für List-Box, ich glaube, Sie leicht ändern können, es mit TreeView zu arbeiten.

XAML:

... 

<Window.Resources> 
    <ContextMenu x:Key="FileContextMenu"> 
     ... 
    </ContextMenu> 
    <ContextMenu x:Key="DirContextMenu"> 
     ... 
    </ContextMenu> 

    <local:ItemToContextMenuConverter x:Key="ContextMenuConverter" />   
</Window.Resources> 

... 

<ListBox x:Name="SomeList"> 
    <ListBox.ItemTemplate> 
     <DataTemplate>       
      <Label Content="{Binding Path=Name}" ContextMenu="{Binding Converter={StaticResource ContextMenuConverter}}"/> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Code:

class Item 
{ 
    public string Name { get; set; } 
    public bool IsFile { get; set; } 
} 

[ValueConversion(typeof(Item), typeof(ContextMenu))] 
public class ItemToContextMenuConverter : IValueConverter 
{ 
    public static ContextMenu FileContextMenu; 
    public static ContextMenu DirContextMenu; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     Item item = value as Item; 
     if (item == null) return null; 

     return item.IsFile ? FileContextMenu : DirContextMenu; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 
} 

private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     ItemToContextMenuConverter.FileContextMenu 
      = this.Resources["FileContextMenu"] as ContextMenu; 
     ItemToContextMenuConverter.DirContextMenu 
      = this.Resources["DirContextMenu"] as ContextMenu; 

     List<Item> items = new List<Item>(); 
     items.Add(new Item() { Name = "First", IsFile = true }); 
     items.Add(new Item() { Name = "Second", IsFile = false }); 

     SomeList.ItemsSource = items; 
    } 
+0

scheint ziemlich perfekt, vielen Dank für die volle Beispiel! – Jared

0

Hallo ich ähnliche Sache auf TreeView tue und ich weiß nicht wie das ItemToContextMenuConverter für jedes Element ausgeführt wird, auch wenn es nicht verwendet wird. Es ist vielleicht in einem kleinen Projekt in Ordnung, aber wenn Sie für jeden MenuItem Code aktivieren/deaktivieren, kann es langsam sein.

Dies ist vielleicht nicht die beste (ich habe gerade mit WPF begonnen), aber ich werde es mit Ihnen teilen.

Menü-Ressourcen:

<Window.Resources> 
    <ContextMenu x:Key="MnuFolderFavorites" StaysOpen="True"> 
    <MenuItem Header="Remove from Favorites" Click="MnuFolder_RemoveFromFavorites_Click"></MenuItem> 
    </ContextMenu> 
    <ContextMenu x:Key="MnuFolder" StaysOpen="True"> 
    <MenuItem Header="New Folder"></MenuItem> 
    <MenuItem Header="Rename" x:Name="MnuFolderRename" Click="MnuFolder_Rename_Click"></MenuItem> 
    <MenuItem Header="Add to Favorites" Click="MnuFolder_AddToFavorites_Click"></MenuItem> 
    </ContextMenu> 
</Window.Resources> 

TreeView:

<TreeView x:Name="TvFolders"> 
    <TreeView.ItemTemplate> 
    <HierarchicalDataTemplate DataType="{x:Type data:Folder}" ItemsSource="{Binding Items}"> 
     <StackPanel Orientation="Horizontal" PreviewMouseRightButtonDown="TvFoldersStackPanel_PreviewMouseRightButtonDown"> 
     <Image Width="20" Height="20" Source="{Binding ImagePath}" /> 
     <TextBlock Text="{Binding Title}" Margin="5,0,0,0" /> 
     </StackPanel> 
    </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

Code:

private void TvFoldersStackPanel_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { 
    ((StackPanel) sender).ContextMenu = null; 
    Data.Folder item = (Data.Folder) ((StackPanel) sender).DataContext; 
    if (!item.Accessible) return; 
    if (item.Parent != null && item.Parent.Title.Equals("Favorites")) { 
    ((StackPanel) sender).ContextMenu = MainWindow.Resources["MnuFolderFavorites"] as ContextMenu; 
    } else { 
    ((StackPanel) sender).ContextMenu = MainWindow.Resources["MnuFolder"] as ContextMenu; 
    foreach (MenuItem menuItem in ((StackPanel) sender).ContextMenu.Items) { 
     switch (menuItem.Name) { 
     case "MnuFolderRename": { 
      menuItem.IsEnabled = item.Parent != null; 
      break; 
     } 
     } 
    } 
    } 
} 

private void MnuFolder_RemoveFromFavorites_Click(object sender, RoutedEventArgs e) { 
    string path = ((Data.Folder)((MenuItem)sender).DataContext).FullPath; 
    Settings.Default.FolderFavorites.Remove(path); 
    Settings.Default.Save(); 
    FavoritesFolder?.AddFavorites(true); 
}