如何在WPF treeview中实现用于选择树节点的命令

如何在WPF treeview中实现用于选择树节点的命令,wpf,xaml,treeview,Wpf,Xaml,Treeview,我再一次在WPF treeview中迷失了方向。 我用一些数据填充了我的treeview,我想在单击节点并在该命令中获取其值时启动一个命令 我的treeview xaml如下所示: <TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left" Margin="0 0 2 0" x:Name="ProjectTree" Grid.C

我再一次在WPF treeview中迷失了方向。
我用一些数据填充了我的treeview,我想在单击节点并在该命令中获取其值时启动一个命令

我的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>

如何在此处单击树视图项时触发命令

解决方案

经过一些实验,它对我来说是这样的:

xaml:


在树视图的视图模型中:
C#

public RelayCommand树取消选择{get;private set;}
只读只读集合\u根节点;
只读PlcAddressViewModel\u根地址;
#区域构造函数
公共项目树视图模型(PlcAddress根地址)
{
_rootAddress=新的PlcAddressViewModel(rootAddress);
_rootNodes=newreadonlycollection(
新的PlcAddressViewModel[]
{
_根地址
});
TreeNodeSelected=新的RelayCommand(ExecuteTreeNodeSelected,canExecuteMethod);
}
#端域构造函数
#区域命令
私有布尔canExecuteMethod(对象参数)
{
返回true;
}
私有void ExecuteTreeNodeSelected(对象参数)
{
PLCADressViewModel selectedNode=(PLCADressViewModel)参数;
Console.WriteLine(“找到此节点:+selectedNode.Name”);
返回;
}
#endregion命令

多亏了@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>

...
...

但是为什么不将
SelectedItem
属性绑定到一个源属性,并在这个属性的setter中处理您的逻辑呢?这将是MVVM实现这一点的方法


编辑:由于
SelectedItem
属性a
TreeView
是只读的,因此必须使用行为才能绑定到它。有一个例子说明了如何做到这一点。

我删除了我的答案,因为与其他解决方案相比,覆盖
TreeViewItem
太复杂了<代码>树视图项相当复杂(包括
切换按钮
项控件
和大量逻辑等)。看见使用
ListBoxItem
执行此操作非常简单,因为它只包含一个
ContentPresenter
,您必须用
按钮来替换它。如果你还感兴趣,请告诉我。发布正确的模板需要一分钟。嗨,BionicCode,非常感谢你的方法。我将首先尝试用mm8提到的方法来做,因为对于像我这样的初学者来说,这似乎有点容易。WPF可能真的很混乱……我喜欢你的方法,因为我已经有了一个IsSelected属性,但我不知道如何通知应用程序的其余部分,这个属性已更改。它不是封装在树上吗?我的意思是,我没有任何事件被触发。(更新了我的问题)如果您有其他问题或改变了方法,请提出新问题。
    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
<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>