C# TreeView在用户选择子项后自动选择父项

C# TreeView在用户选择子项后自动选择父项,c#,wpf,textbox,treeview,selecteditemchanged,C#,Wpf,Textbox,Treeview,Selecteditemchanged,在我的窗口中,我有一个树视图和文本框。假设TextBox用于编写自定义脚本,而TreeView是选择要插入的函数的一种方式;想想水晶报告脚本编辑器 我的目标是让用户单击树视图的一个子项,然后将该子项插入文本框。子节点是函数签名,位于父节点下。然后,用户可以导航到文本框,选择一个函数参数,并将其替换为另一个函数签名。为了实现这一点,我处理TreeView的SelectedItemChanged事件,设置文本框的SelectedText,然后尝试在更改后突出显示文本 已正确交换文本框的Selecte

在我的窗口中,我有一个树视图和文本框。假设TextBox用于编写自定义脚本,而TreeView是选择要插入的函数的一种方式;想想水晶报告脚本编辑器

我的目标是让用户单击树视图的一个子项,然后将该子项插入文本框。子节点是函数签名,位于父节点下。然后,用户可以导航到文本框,选择一个函数参数,并将其替换为另一个函数签名。为了实现这一点,我处理TreeView的SelectedItemChanged事件,设置文本框的SelectedText,然后尝试在更改后突出显示文本

已正确交换文本框的SelectedText。但是,文本不会突出显示,滚动条也不会滚动到所选文本

这是我编写的测试项目中的XAML,用于重现行为:

  <Window x:Class="SelectedTextWeirdness.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
          xmlns:SelectedTextWeirdness="clr-namespace:SelectedTextWeirdness" Title="MainWindow" Width="600" Height="600"
          x:Name="Me">
     <Grid>
        <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TreeView Grid.Row="0" x:Name="treeView" ItemsSource="{Binding ElementName=Me, Path=TreeViewItems, Mode=TwoWay}" 
                  SelectedItemChanged="treeView_SelectedItemChanged" Margin="10">
           <TreeView.Resources>
              <HierarchicalDataTemplate DataType="{x:Type SelectedTextWeirdness:Parent}" ItemsSource="{Binding Children}">
                 <TextBlock Text="{Binding Name}" />
              </HierarchicalDataTemplate>
              <DataTemplate DataType="{x:Type SelectedTextWeirdness:Child}">
                 <TextBlock Text="{Binding Name}" />
              </DataTemplate>
           </TreeView.Resources>
        </TreeView>
        <TextBox Grid.Row="1" x:Name="scriptTextBox" Margin="10" Height="200" Width="Auto" FontFamily="Consolas, Courier New" 
                 HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto"
                 MaxLines="9999" AcceptsReturn="True" AcceptsTab="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                 Text="{Binding Path=Script, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                 />
     </Grid>
  </Window>
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  using System.Windows.Navigation;
  using System.Windows.Shapes;

  namespace SelectedTextWeirdness
  {
     public class Child
     {
        public string Name
        {
           get;
           set;
        }
     }

     public class Parent
     {
        public string Name
        {
           get;
           set;
        }

        public List<Child> Children
        {
           get;
           set;
        }   
     }

     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
        public List<Parent> TreeViewItems
        {
           get;
           set;
        }

        public MainWindow()
        {
           BuildTreeViewItems();

           InitializeComponent();
        }

        private void BuildTreeViewItems()
        {
           TreeViewItems = new List<Parent>()
                              {
                                 new Parent()
                                    {
                                       Name = "Parent1",
                                       Children =
                                          new List<Child>()
                                             {
                                                new Child() {Name = "ReallyLongFunctionNameNumber1(ReallyLongLeft1, ReallyLongRight1)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber2(ReallyLongLeft2, ReallyLongRight2)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber3(ReallyLongLeft3, ReallyLongRight3)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber4(ReallyLongLeft4, ReallyLongRight4)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber5(ReallyLongLeft5, ReallyLongRight5)"}
                                             }
                                    },
                                 new Parent()
                                    {
                                       Name = "Parent2",
                                       Children =
                                          new List<Child>()
                                             {
                                                new Child() {Name = "ReallyLongFunctionNameNumber1(ReallyLongLeft1, ReallyLongRight1)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber2(ReallyLongLeft2, ReallyLongRight2)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber3(ReallyLongLeft3, ReallyLongRight3)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber4(ReallyLongLeft4, ReallyLongRight4)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber5(ReallyLongLeft5, ReallyLongRight5)"}
                                             }
                                    }
                              };
        }

        private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
           var tree = (TreeView)sender;
           var selectedItem = tree.SelectedItem as Child;
           if (selectedItem != null)
           {
              int selectionStart = scriptTextBox.SelectionStart;
              string selectedText = selectedItem.Name;
              scriptTextBox.SelectedText = selectedText;
              scriptTextBox.Focus();            
              scriptTextBox.Select(selectionStart, selectedText.Length);
           }
        }
     }
  }

下面是隐藏的代码:

  <Window x:Class="SelectedTextWeirdness.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
          xmlns:SelectedTextWeirdness="clr-namespace:SelectedTextWeirdness" Title="MainWindow" Width="600" Height="600"
          x:Name="Me">
     <Grid>
        <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TreeView Grid.Row="0" x:Name="treeView" ItemsSource="{Binding ElementName=Me, Path=TreeViewItems, Mode=TwoWay}" 
                  SelectedItemChanged="treeView_SelectedItemChanged" Margin="10">
           <TreeView.Resources>
              <HierarchicalDataTemplate DataType="{x:Type SelectedTextWeirdness:Parent}" ItemsSource="{Binding Children}">
                 <TextBlock Text="{Binding Name}" />
              </HierarchicalDataTemplate>
              <DataTemplate DataType="{x:Type SelectedTextWeirdness:Child}">
                 <TextBlock Text="{Binding Name}" />
              </DataTemplate>
           </TreeView.Resources>
        </TreeView>
        <TextBox Grid.Row="1" x:Name="scriptTextBox" Margin="10" Height="200" Width="Auto" FontFamily="Consolas, Courier New" 
                 HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto"
                 MaxLines="9999" AcceptsReturn="True" AcceptsTab="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                 Text="{Binding Path=Script, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                 />
     </Grid>
  </Window>
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  using System.Windows.Navigation;
  using System.Windows.Shapes;

  namespace SelectedTextWeirdness
  {
     public class Child
     {
        public string Name
        {
           get;
           set;
        }
     }

     public class Parent
     {
        public string Name
        {
           get;
           set;
        }

        public List<Child> Children
        {
           get;
           set;
        }   
     }

     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
        public List<Parent> TreeViewItems
        {
           get;
           set;
        }

        public MainWindow()
        {
           BuildTreeViewItems();

           InitializeComponent();
        }

        private void BuildTreeViewItems()
        {
           TreeViewItems = new List<Parent>()
                              {
                                 new Parent()
                                    {
                                       Name = "Parent1",
                                       Children =
                                          new List<Child>()
                                             {
                                                new Child() {Name = "ReallyLongFunctionNameNumber1(ReallyLongLeft1, ReallyLongRight1)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber2(ReallyLongLeft2, ReallyLongRight2)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber3(ReallyLongLeft3, ReallyLongRight3)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber4(ReallyLongLeft4, ReallyLongRight4)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber5(ReallyLongLeft5, ReallyLongRight5)"}
                                             }
                                    },
                                 new Parent()
                                    {
                                       Name = "Parent2",
                                       Children =
                                          new List<Child>()
                                             {
                                                new Child() {Name = "ReallyLongFunctionNameNumber1(ReallyLongLeft1, ReallyLongRight1)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber2(ReallyLongLeft2, ReallyLongRight2)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber3(ReallyLongLeft3, ReallyLongRight3)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber4(ReallyLongLeft4, ReallyLongRight4)"},
                                                new Child() {Name = "ReallyLongFunctionNameNumber5(ReallyLongLeft5, ReallyLongRight5)"}
                                             }
                                    }
                              };
        }

        private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
           var tree = (TreeView)sender;
           var selectedItem = tree.SelectedItem as Child;
           if (selectedItem != null)
           {
              int selectionStart = scriptTextBox.SelectionStart;
              string selectedText = selectedItem.Name;
              scriptTextBox.SelectedText = selectedText;
              scriptTextBox.Focus();            
              scriptTextBox.Select(selectionStart, selectedText.Length);
           }
        }
     }
  }
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
名称空间选择的文本古怪
{
公营儿童
{
公共字符串名
{
得到;
设置
}
}
公共类父类
{
公共字符串名
{
得到;
设置
}
公开儿童名单
{
得到;
设置
}   
}
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共列表树项
{
得到;
设置
}
公共主窗口()
{
BuildTreeViewItems();
初始化组件();
}
私有void BuildTreeViewItems()
{
TreeViewItems=新列表()
{
新父项()
{
Name=“Parent1”,
孩子们=
新名单()
{
新建子项(){Name=“ReallyLongFunctionNameNumber1(ReallyLongLeft1,ReallyLongRight1)”,
新建子项(){Name=“ReallyLongFunctionNameNumber2(ReallyLongLeft2,ReallyLongRight2)”,
新建子项(){Name=“ReallyLongFunctionNameNumber3(ReallyLongLeft3,ReallyLongRight3)”,
新建子项(){Name=“ReallyLongFunctionNameNumber4(ReallyLongLeft4,ReallyLongRight4)”,
新建子项(){Name=“ReallyLongFunctionNameNumber5(ReallyLongLeft5,ReallyLongRight5)”}
}
},
新父项()
{
Name=“Parent2”,
孩子们=
新名单()
{
新建子项(){Name=“ReallyLongFunctionNameNumber1(ReallyLongLeft1,ReallyLongRight1)”,
新建子项(){Name=“ReallyLongFunctionNameNumber2(ReallyLongLeft2,ReallyLongRight2)”,
新建子项(){Name=“ReallyLongFunctionNameNumber3(ReallyLongLeft3,ReallyLongRight3)”,
新建子项(){Name=“ReallyLongFunctionNameNumber4(ReallyLongLeft4,ReallyLongRight4)”,
新建子项(){Name=“ReallyLongFunctionNameNumber5(ReallyLongLeft5,ReallyLongRight5)”}
}
}
};
}
私有无效树查看\u SelectedItemChanged(对象发送方,RoutedPropertyChangedEventArgs e)
{
var-tree=(TreeView)发送方;
var selectedItem=tree.selectedItem作为子级;
如果(selectedItem!=null)
{
int-selectionStart=scriptTextBox.selectionStart;
string selectedText=selectedItem.Name;
scriptTextBox.SelectedText=SelectedText;
scriptTextBox.Focus();
scriptTextBox.Select(selectionStart,selectedText.Length);
}
}
}
}
我已尝试设置SelectedItemChanged e.Handled=true。那没用。我尝试过处理文本框的LostFocus并设置e.Handled=true,但没有成功。这似乎只有在使用HierarchycalDateTemplate时才会发生。如果我将数据更改为仅一个级别,则此设置工作正常


有什么想法吗?

核心问题是在事件处理程序中进行
Focus()
更改。通过在
BeginInvoke
中调用焦点来延迟焦点

比如:

delegate void voidDelegate();

private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    var tree = (TreeView)sender;
    var selectedItem = tree.SelectedItem as Child;
    if (selectedItem != null)
    {
        int selectionStart = scriptTextBox.SelectionStart;
        string selectedText = selectedItem.Name;
        voidDelegate giveFocusDelegate = new  voidDelegate(giveFocus);  
        Dispatcher.BeginInvoke(giveFocusDelegate, new object[] { });
        scriptTextBox.SelectedText = selectedText;         
    }
}

private void giveFocus()
{
    scriptTextBox.Focus();
}    
delegate void voidDelegate();
私有无效树查看\u SelectedItemChanged(对象发送方,RoutedPropertyChangedEventArgs e)
{
var-tree=(TreeView)发送方;
var selectedItem=tree.selectedItem作为子级;
如果(selectedItem!=null)
{
在里面