C# WPF如何根据treeviewitem类型更改contextmenu项?
我有一个项目的C# WPF如何根据treeviewitem类型更改contextmenu项?,c#,wpf,xaml,treeview,contextmenu,C#,Wpf,Xaml,Treeview,Contextmenu,我有一个项目的TreeView,我希望只为第二层项目弹出一个ContextMenu。我该怎么做呢?我假设您正在将TreeView绑定到一个项目列表。如果是,第一层和第二层项目是否或是否可以具有不同的数据类型?然后,您可以对第一层类型执行hierarchycaldatatemplate,对第二层类型执行DataTemplate,如下所示: <HierarchicalDataTemplate DataType="{x:Type local:FirstTierType}" ItemsSource
TreeView
,我希望只为第二层项目弹出一个ContextMenu
。我该怎么做呢?我假设您正在将TreeView
绑定到一个项目列表。如果是,第一层和第二层项目是否或是否可以具有不同的数据类型?然后,您可以对第一层类型执行hierarchycaldatatemplate
,对第二层类型执行DataTemplate
,如下所示:
<HierarchicalDataTemplate DataType="{x:Type local:FirstTierType}" ItemsSource="{Binding Items}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:SecondTierType}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="whatever1" Command="whatever1cmd"></MenuItem>
<MenuItem Header="whatever2" Command="whatever2cmd"></MenuItem>
<MenuItem Header="whatever3" Command="whatever2cmd"></MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
.
.
.
<TreeView ItemsSource="{Binding Items}" />
.
.
.
您可以混合使用一些技巧来实现这一点,其要点是创建一个IValueConverter,该转换器允许您从HierarchicalDataTemplate内部传递一个FrameworkElement,并确定保存当前项的TreeViewItem是否为顶级TreeViewItem。这是通过遍历wpf应用程序的VisualTree并找到重要的TreeViewItem来实现的。如果给定的TreeViewItem没有TreeViewItem类型的祖先,那么您知道它必须是顶级项。我们可以在样式中使用此信息来设置TreeView项上ContextMenu的值。代码如下:
XAML:
<Window x:Class="TreeViewContextMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewContextMenu"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<local:TreeViewItemToTopLevelConverter x:Key="treeViewConverter"/>
<ContextMenu x:Key="contextMenu">
<MenuItem Header="MenuItemHeader"/>
</ContextMenu>
</Grid.Resources>
<TreeView ItemsSource="{Binding Items}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Part}" ItemsSource="{Binding SubParts}">
<TextBlock Text="{Binding Name}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource treeViewConverter}}" Value="False">
<DataTrigger.Setters>
<Setter Property="ContextMenu" Value="{StaticResource contextMenu}"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
代码隐藏和视图模型:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
public class ViewModel : PropertyChangedNotifier
{
public ViewModel()
{
Items = new ObservableCollection<Part>();
var parent = new Part() { Name = "Parent" };
parent.SubParts = new ObservableCollection<Part>();
parent.SubParts.Add(new Part() { Name = "Child1" });
parent.SubParts.Add(new Part() { Name = "Child2" });
Items.Add(parent);
}
private ObservableCollection<Part> _items;
public ObservableCollection<Part> Items
{
get
{
return _items;
}
set
{
_items = value;
OnPropertyChanged("Items");
}
}
}
public class Part : PropertyChangedNotifier
{
private string _name;
private ObservableCollection<Part> _subParts;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public ObservableCollection<Part> SubParts
{
get { return _subParts; }
set
{
_subParts = value;
OnPropertyChanged("SubParts");
}
}
}
public class PropertyChangedNotifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public static class VisualTreeTools
{
public static T GetVisualParent<T>(DependencyObject item) where T : DependencyObject
{
while (item != null)
{
item = VisualTreeHelper.GetParent(item);
if (item is T)
return item as T;
}
return null;
}
}
public class TreeViewItemToTopLevelConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var item = value as DependencyObject;
if (item == null)
return 0;
var containerTreeViewItem = VisualTreeTools.GetVisualParent<TreeViewItem>(item);
var parentTreeViewItem = VisualTreeTools.GetVisualParent<TreeViewItem>(containerTreeViewItem);
return parentTreeViewItem == null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
this.DataContext=newviewmodel();
}
}
公共类ViewModel:PropertyChangedNotifier
{
公共视图模型()
{
Items=新的ObservableCollection();
var parent=newpart(){Name=“parent”};
parent.SubParts=新的ObservableCollection();
添加(新部件(){Name=“Child1”});
添加(新部件(){Name=“Child2”});
添加(父项);
}
私人可观测收集项目;
公共可观测收集项目
{
得到
{
退货(物品);;
}
设置
{
_项目=价值;
不动产变更(“项目”);
}
}
}
公共类部分:PropertyChangedNotifier
{
私有字符串\u名称;
私人可观测采集子部分;
公共字符串名
{
得到
{
返回_name;
}
设置
{
_名称=值;
不动产变更(“名称”);
}
}
公共可观测集合子部分
{
获取{return\u子部分;}
设置
{
_子部分=价值;
财产变更(“子部分”);
}
}
}
公共类PropertyChangedNotifier:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共void OnPropertyChanged(字符串propertyName)
{
var propertyChanged=propertyChanged;
if(propertyChanged!=null)
{
propertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
公共静态类VisualTreeTools
{
公共静态T GetVisualParent(DependencyObject项),其中T:DependencyObject
{
while(项!=null)
{
item=VisualTreeHelper.GetParent(项目);
如果(项目为T)
返回项目为T;
}
返回null;
}
}
公共类TreeViewItemToTopLevel转换器:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
var item=作为DependencyObject的值;
如果(项==null)
返回0;
var containerTreeViewItem=VisualTreeTools.GetVisualParent(项目);
var parentTreeViewItem=VisualTreeTools.GetVisualParent(containerTreeViewItem);
返回parentTreeViewItem==null;
}
公共对象转换回(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
如果您为您的TreeView发布一些XAML,这将非常有用。例如,您是否使用HierarchycalDataTemplate?