2016-09-15 2 views
0

Мне удалось реализовать TreeView успешно, и я использую интерфейс в качестве шаблона для отображения данных для Project/Folder/File, так же как SolutionExplorer Visual Studio. Я хочу добавить contextmenu в свой TreeViewItem на основе типа элемента, как описано в моем файле xaml ниже. Но мне не удалось сопоставить контекстное меню на основе TreeViewItem. Я попытался выяснить, могу ли я использовать триггеры, которые работают, но я не знаю, как назначить ContextMenu на основе типов TreeViewItem (например, Folder/File/Project в моем случае).Различные контекстные меню для каждого типа treeviewitem в wpf MVVM

<!--<Trigger Property="IsSelected" Value="Folder"> 
         <Setter Property="ContextMenu" Value="{StaticResource FolderMenu}" /> 
    </Trigger>--> 

<Window x:Class="SimpleTreeWpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:SimpleTreeWpfApplication1" 
    mc:Ignorable="d" 

    Title="MainWindow" Height="350" Width="525"> 
<Window.DataContext> 
    <local:TreeViewModel/> 
</Window.DataContext> 
<Grid> 
    <TextBlock Text="Hierarchical root binding" Foreground="Red" Margin="10,20,0,0"/> 
    <TreeView ItemsSource="{Binding TreeData}" Margin="10" Height="200"> 
     <TreeView.Resources> 
      <!-- Begin Context Menu --> 
      <ContextMenu x:Key="ProjectMenu" > 
       <MenuItem Command="{Binding AddFolder}" Header="Add Folder"/> 
       <MenuItem Command="{Binding EditProject}" Header="Edit"/> 
      </ContextMenu> 
      <ContextMenu x:Key="FolderMenu" > 
       <MenuItem Command="{Binding AddFolder}" Header="Add Folder"/> 
       <MenuItem Command="{Binding AddFile}" Header="Add File"/> 
      </ContextMenu> 
      <ContextMenu x:Key="FileMenu" > 
       <MenuItem Command="{Binding EditFile}" Header="Edit"/>     
      </ContextMenu> 
     </TreeView.Resources> 
     <TreeView.ItemContainerStyle> 

      <Style TargetType="{x:Type TreeViewItem}"> 
       <Setter Property="ContextMenu" Value="{StaticResource FolderMenu}"/> 
       <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> 
       <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
       <Setter Property="FontWeight" Value="Normal" /> 
       <Style.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="FontWeight" Value="Bold" /> 
        </Trigger> 

       </Style.Triggers> 
      </Style> 
     </TreeView.ItemContainerStyle> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type local:INode}"> 
       <TreeViewItem Header="{Binding Label}"/> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 

</Grid> 

Интерфейс и модели выглядят, как показано ниже:

public interface INode 
    { 
    string FullPath { get; } 
    string Label { get; } 
    List<INode> Children { get; } 
} 


    public class Folder : INode 
    { 
    public List<INode> Children { get; set; } 
    public string Label { get; set; } 
    public string FullPath { get; set; } 
    //custom values 
    public Dictionary<string,string> MyFolderProperties { get; set; } 

    //initialize default values 
    public Folder() 
    { 
     Children = new List<INode>(); 
    } 
} 


public class File : INode 
    { 
    public List<INode> Children { get; set; } 
    public string Label { get; set; } 
    public string FullPath { get; set; } 

    //custom values 
    public Dictionary<string,string> MyFileProperties { get; set; } 
} 


public class Project: INode 
    { 
    public List<INode> Children { get; set; } 
    public string Label { get; set; } 
    public string FullPath { get; set; } 

    public List<String> ProjectTypeValuesDb { get; set; } 

    //initialize default values 
    public Project() 
    { 
     Children = new List<INode>(); 
    } 
} 



//Viewmodel code 
public class TreeViewModel : INotifyPropertyChanged 
{ 
    public TreeViewModel() 
    { 

     //initialize and add 
     m_folders = new List<INode>(); 
     TreeData = m_folders; 
     //add Root items 
     TreeData.Add(new Folder { Label = "Folder1", FullPath = @"C:\dummy1" }); 
     TreeData.Add(new Folder { Label = "Folder2", FullPath = @"C:\dummy2" }); 
     TreeData.Add(new Folder { Label = "Folder3", FullPath = @"C:\dummy3" }); 
     TreeData.Add(new Folder { Label = "Folder4", FullPath = @"C:\dummy4" }); 
     //Folders.Add(new File { Label = "File1.txt", FullPath = @"C:\File1.txt" }); 

     //add sub items 
     TreeData[0].Children.Add(new Folder { Label = "Folder11", FullPath = @"C:\dummy11" }); 
     TreeData[0].Children.Add(new Folder { Label = "Folder12", FullPath = @"C:\dummy12" }); 
     TreeData[0].Children.Add(new Folder { Label = "Folder13", FullPath = @"C:\dummy13" }); 
     TreeData[0].Children.Add(new Folder { Label = "Folder14", FullPath = @"C:\dummy14" }); 

     TreeData[0].Children.Add(new File { Label = "File1.txt", FullPath = @"C:\File1.txt" }); 
     TreeData[0].Children.Add(new File { Label = "File2.txt", FullPath = @"C:\File1.txt" }); 
     TreeData[0].Children.Add(new File { Label = "File3.txt", FullPath = @"C:\File1.txt" }); 

    } 



    bool _isExpanded = false; 
    bool _isSelected = false; 
    #region IsExpanded 
    /// <summary> 
    /// Gets/sets whether the TreeViewItem 
    /// </summary> 
    public bool IsExpanded 
    { 
     get { return _isExpanded; } 
     set 
     { 
      if (value != _isExpanded) 
      { 
       _isExpanded = value; 
       this.NotifiyPropertyChanged("IsExpanded"); 
      } 

      // Expand all the way up to the root. 
      //if (_isExpanded && _parent != null) 
      // _parent.IsExpanded = true; 
     } 
    } 

#endregion // IsExpanded 

    #region IsSelected 

    /// <summary> 
    /// Gets/sets whether the TreeViewItem 
    /// associated with this object is selected. 
    /// </summary> 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      if (value != _isSelected) 
      { 
       _isSelected = value; 
       this.NotifiyPropertyChanged("IsSelected"); 
      } 
     } 
    } 

    #endregion // IsSelected 

    private List<INode> m_folders; 
    public List<INode> TreeData 
    { 
     get { return m_folders; } 
     set 
     { 
      m_folders = value; 
      NotifiyPropertyChanged("Folders"); 
     } 
    } 

    void NotifiyPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

ответ

0

Это довольно простой HierarchicalDataTemplate. Просто клонируйте его для DataType="{x:Type local:Folder}", DataType="{x:Type local:File}" и т. Д. И укажите соответствующие ContextMenu в TreeViewItem в каждом шаблоне. Вы определяете шаблоны в TreeView.Resources, а не в ItemTemplate.