我能够成功实现TreeView,并且我使用Interface作为模板来显示Project / Folder / File的数据,就像Visual Studio的SolutionExplorer一样。我想根据项目类型将contextmenu添加到我的TreeViewItem,如下面的xaml文件中所述。但我无法根据TreeViewItem映射上下文菜单。我试着看看我是否可以使用有效的触发器,但我不知道如何根据TreeViewItem类型分配ContextMenu(例如我的情况下的Folder / File / Project)。
<!--<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 :(得分:0)
这很简单HierarchicalDataTemplate
。只需将其克隆为DataType="{x:Type local:Folder}"
,DataType="{x:Type local:File}"
等,并为每个模板中的ContextMenu
提供相应的TreeViewItem
。您可以在TreeView.Resources
而不是ItemTemplate
属性中定义模板。