如何在 WPF 树视图中实现选择树节点的命令
HowTo implement commands for selection of treenodes in WPF treeview
再一次,我对 WPF 树视图有点迷路了。
我用一些数据填充了树视图,我想在单击节点并在该命令中获取其值时触发命令。
我的 treeview-xaml 看起来像这样:
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left" Margin="0 0 2 0" x:Name="ProjectTree" Grid.Column="0">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<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}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
如何在点击此处的 treeviewitem 时触发命令?
解决方案
经过一些实验,它对我有用:
xaml:
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding TreeNodeSelected}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<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}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
在树视图的视图模型中:
C#
public RelayCommand TreeNodeSelected { get; private set; }
readonly ReadOnlyCollection<PlcAddressViewModel> _rootNodes;
readonly PlcAddressViewModel _rootAddress;
#region Constructor
public ProjectTreeviewModel(PlcAddress rootAddress)
{
_rootAddress = new PlcAddressViewModel(rootAddress);
_rootNodes = new ReadOnlyCollection<PlcAddressViewModel>(
new PlcAddressViewModel[]
{
_rootAddress
});
TreeNodeSelected = new RelayCommand(ExecuteTreeNodeSelected, canExecuteMethod);
}
#endregion Constructor
#region Commands
private bool canExecuteMethod(object parameter)
{
return true;
}
private void ExecuteTreeNodeSelected(object parameter)
{
PlcAddressViewModel selectedNode = (PlcAddressViewModel)parameter;
Console.WriteLine("Found this node: " + selectedNode.Name);
return;
}
#endregion Commands
感谢@mm8 和@BionicCode
您可以使用交互触发器处理事件,例如 SelectedItemChanged
:
<TreeView DataContext="{Binding ProjectTree}"
ItemsSource="{Binding ProjectNode}"
x:Name="ProjectTree"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
...
</TreeView.ItemContainerStyle>
...
</TreeView>
Handling events in an MVVM WPF application
How to add System.Windows.Interactivity to project?
但你为什么不直接将 SelectedItem
属性 绑定到源 属性 并在 setter 中处理你的逻辑一?这将是 MVVM 的方式。
编辑:由于 SelectedItem
属性 a TreeView
是只读的,您必须使用行为才能绑定到它。有一个如何执行此操作的示例 here.
再一次,我对 WPF 树视图有点迷路了。
我用一些数据填充了树视图,我想在单击节点并在该命令中获取其值时触发命令。
我的 treeview-xaml 看起来像这样:
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left" Margin="0 0 2 0" x:Name="ProjectTree" Grid.Column="0">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<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}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
如何在点击此处的 treeviewitem 时触发命令?
解决方案
经过一些实验,它对我有用:
xaml:
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding TreeNodeSelected}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<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}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
在树视图的视图模型中:
C#
public RelayCommand TreeNodeSelected { get; private set; }
readonly ReadOnlyCollection<PlcAddressViewModel> _rootNodes;
readonly PlcAddressViewModel _rootAddress;
#region Constructor
public ProjectTreeviewModel(PlcAddress rootAddress)
{
_rootAddress = new PlcAddressViewModel(rootAddress);
_rootNodes = new ReadOnlyCollection<PlcAddressViewModel>(
new PlcAddressViewModel[]
{
_rootAddress
});
TreeNodeSelected = new RelayCommand(ExecuteTreeNodeSelected, canExecuteMethod);
}
#endregion Constructor
#region Commands
private bool canExecuteMethod(object parameter)
{
return true;
}
private void ExecuteTreeNodeSelected(object parameter)
{
PlcAddressViewModel selectedNode = (PlcAddressViewModel)parameter;
Console.WriteLine("Found this node: " + selectedNode.Name);
return;
}
#endregion Commands
感谢@mm8 和@BionicCode
您可以使用交互触发器处理事件,例如 SelectedItemChanged
:
<TreeView DataContext="{Binding ProjectTree}"
ItemsSource="{Binding ProjectNode}"
x:Name="ProjectTree"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
...
</TreeView.ItemContainerStyle>
...
</TreeView>
Handling events in an MVVM WPF application
How to add System.Windows.Interactivity to project?
但你为什么不直接将 SelectedItem
属性 绑定到源 属性 并在 setter 中处理你的逻辑一?这将是 MVVM 的方式。
编辑:由于 SelectedItem
属性 a TreeView
是只读的,您必须使用行为才能绑定到它。有一个如何执行此操作的示例 here.