I have a TreeView, displaying information using TextBox, with the ability to edit. But the TextBox stops the MouseDown event and the selection of the TreeViewItem does not occur when the TextBox is clicked. How to solve this problem by leaving the ability to edit the text.
Smallest possible example: In this code, the SelectedItemChanged event is not fired because no item is selected.
<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> {};
}
}
I tried to use this, but it didn't work as I expected. Perhaps I am using it incorrectly.
AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(StackPanel_MouseDown), true);
or
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
Thanks in advance!
CodePudding user response:
A straightforward way is to connect IsKeyboardFocused property of TextBox with IsSelected property of TreeViewItem. It can be done easily by 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>
