用户选择子项后,TreeView自动选择父级

在我的窗口中,我有一个TreeView和TextBox。 假设TextBox用于编写自定义脚本,TreeView是一种选择要插入的函数的方法; 想想Crystal Report脚本编辑器。

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

正确交换TextBox的SelectedText。 但是,文本未突出显示,滚动条未滚动到所选文本。

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

                   

这是代码隐藏:

  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 Children { get; set; } } ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public List TreeViewItems { get; set; } public MainWindow() { BuildTreeViewItems(); InitializeComponent(); } private void BuildTreeViewItems() { TreeViewItems = new List() { new Parent() { Name = "Parent1", Children = new List() { 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() { 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 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); } } } } 

我尝试过设置SelectedItemChanged e.Handled = true。 那没用。 我已经尝试处理TextBox的LostFocus并设置e.Handled = true,但是没有用。 这似乎只在我使用HierarchicalDateTemplate时发生。 如果我将数据更改为仅一个级别,此设置正常。

有任何想法吗?

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

就像是:

 delegate void voidDelegate(); private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs 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(); } 

应该让你离目标更近。

编辑:我们怎么知道这会起作用?

正如Dispatcher.BeginInvoke的文档所说:

该操作将添加到指定DispatcherPriority的Dispatcher的事件队列中。

因此,无论您调用beginInvoke的任务的优先级如何,调用可能发生的最近时间是在当前操作的执行结束之后:beginInvoked操作在调度程序队列的某处“推送”,该操作在单个上运行线。