WPF 中带有 TextBox 的 TreeViewItem:单击 TextBox 时如何选择包含 TextBox 的 TreeViewItem

TreeViewItem with TextBox in WPF: How selected TreeViewItem containing a TextBox when clicking on TextBox

我有一个 TreeView,使用 TextBox 显示信息,具有编辑功能。 但是 TextBox 会停止 MouseDown 事件,并且在单击 TextBox 时不会选择 TreeViewItem。 如何通过保留编辑文本的能力来解决这个问题。

可能的最小示例:在此代码中,未触发 SelectedItemChanged 事件,因为未选择任何项目。

<Window x:Class="TreeViewItemSelected.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <TextBlock x:Name="text" FontSize="20" HorizontalAlignment="Center" />
        <TreeView  x:Name="tree" FontSize="20" ItemsSource="{Binding Items}" SelectedItemChanged="tree_SelectedItemChanged">           
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Items}">
                    <TextBox Text="{Binding Name}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </StackPanel>   
</Window>
using System.Collections.ObjectModel;
using System.Windows;
namespace TreeViewItemSelected
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new VM();
        }

        private void tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) 
        {
            if (e.NewValue is testitem item) text.Text = item?.Name;
        }
    }
    public class VM
    {
        public VM()
        {
            testitem item = new testitem("Aaaaaaa");
            item.Items.Add(new testitem("Aaa  1"));
            item.Items.Add(new testitem("Aaa  2"));
            item.Items.Add(new testitem("Aaa  3"));
            Items.Add(item);
            item = new testitem("Bbbbbbb");
            item.Items.Add(new testitem("Bbb  1"));
            item.Items.Add(new testitem("Bbb  2"));
            item.Items.Add(new testitem("Bdd  3"));
            Items.Add(item);
            Items.Add(new testitem("Ccccccc"));
            Items.Add(new testitem("Ddddddd"));
            Items.Add(new testitem("Eeeeeee"));
        }

        public ObservableCollection<testitem> Items { get; set; } = new ObservableCollection<testitem>();
    }
    public class testitem 
    {
        public string Name { get; set; }
        public testitem(string name) => Name = name;
        public ObservableCollection<testitem> Items { get; set; } = new ObservableCollection<testitem> {};
    }
}

我尝试使用它,但它没有像我预期的那样工作。可能是我用错了。

   AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(StackPanel_MouseDown), true);

    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Setter Property="IsSelected" Value="True"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>

提前致谢!

一种直接的方法是将 TextBoxIsKeyboardFocused 属性 与 TreeViewItemIsSelected 属性 连接起来。 Microsoft.Xaml.Behaviors.Wpf.

可以轻松完成
<TextBox Text="{Binding Name}">
    <i:Interaction.Triggers>
        <i:DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBox}}, Path=IsKeyboardFocused}" Value="True">
            <i:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
                                    PropertyName="IsSelected" Value="True"/>
        </i:DataTrigger>
    </i:Interaction.Triggers>
</TextBox>