TreeView控件自动选择父用户选择过了一会儿 [英] TreeView auto-selecting parent after user selects child

查看:178
本文介绍了TreeView控件自动选择父用户选择过了一会儿的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的窗口,我有一个TreeView和TextBox。假装文本框用于编写自定义脚本和TreeView的是一种方法,选择一个功能接入;认为水晶报表的脚本编辑器。

In my window I have a TreeView and TextBox. Pretend the TextBox is used for writing a custom script and the TreeView is a way to select a function to insert; think Crystal Report script editor.

我的目标是让用户单击TreeView中的孩子之一,且该子女插入到文本框。孩子是一个函数签名,并驻留在父节点下。然后,用户可以导航到该文本框,选择功能参数之一,另一个函数签名代替它。要做到这一点,我处理TreeView的SelectedItemChanged事件,设置文本框的SelectedText,然后尽量突出它改变后的文字。

My goal is for a user to click one of the children of the TreeView and that child inserts into the TextBox. The child is a function signature and resides under a Parent node. The user can then navigate to the TextBox, select one of the function parameters and replace it with another function signature. To accomplish this, I handle the TreeView's SelectedItemChanged event, set the TextBox's SelectedText, and then try to highlight the text after it's changed.

TextBox的SelectedText正确正在交换。但是,文本没有被突出显示,并滚动条滚动不向选定的文本。

The SelectedText of the TextBox is properly being swapped. However, the text is not being highlighted and the scrollbar isn't scrolling to the selected text.

下面是测试项目,我写重现我的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);
           }
        }
     }
  }



我已经尝试设置SelectedItemChanged e.Handled = TRUE。没有工作。我试过处理TextBox的引发LostFocus和设置e.Handled =真实的,没有奏效。这似乎只当我使用HierarchicalDateTemplate发生。如果我改变的数据只有一个级别,这种设置工作正常。

I have tried setting the SelectedItemChanged e.Handled = true. That didn't work. I've tried handling the LostFocus of the TextBox and setting e.Handled = true and that hasn't worked. This only seems to happen when I use the HierarchicalDateTemplate. If I change the data to be one level only, this setup works fine.

任何想法?

推荐答案

THX一个良好的书面问题。
中的核心问题是有一个事件处理程序中的一个焦点()的变化。由BeginInvoke的内调用它推迟福克斯结果
是这样的:

Thx for a well-written question. The core issue is to have a Focus() change within an event handler. Postpone the Focus by calling it within a BeginInvoke.
Something like :

    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();
    }   



应该让你从你的目标越来越近。

Should get you closer from your goal.

编辑:我们怎么知道这将工作

Edit : How do we know this will work ?

由于文件说:
http://msdn.microsoft.com/fr -fr /库/ system.windows.threading.dispatcher.begininvoke(v = vs.110)的.aspx

该操作被添加到分派的事件队列在
中规定的DispatcherPriority

The operation is added to the event queue of the Dispatcher at the specified DispatcherPriority.

所以,无论该任务的优先级在那里你调用BeginInvoke,当调用可能发生的是之后当前操作的执行终止最近的时间为:beginInvoked操作的调度,它在单个线程的工作队列推的地方。

So whatever the priority of the task where you call beginInvoke, the nearest time when the call can happen is right after the execution of current operation ended : the beginInvoked operation is 'pushed' somewhere on the queue of the dispatcher, which works on a single thread.

这篇关于TreeView控件自动选择父用户选择过了一会儿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆