zoukankan      html  css  js  c++  java
  • WPF 之 TreeView右键选中节点及节点重命名

      下面的TreeView节点是通过数据双向绑定的方式,绑定到TextBlock控件和TextBox控件的Text属性上,并且让两者绑定相同的属性,同时使TextBox控件刚好完全覆盖TextBlock控件, 由于TextBlock控件和TextBox控件的区别,TextBlock控件无法实现编辑,所以我在TextBlock控件的上面覆盖了一个TextBox控件,初始状态下我们设置TextBox的Visibility属性为Collapsed,当我们点击重命名的时候,我们再设置TextBox的Visibility属性为Visible,这样我们就能够进行节点的重命名,当然当我们命名完成后(该TextBox失去焦点之后)我们再设置TextBox的Visibility属性为Collapsed,这样就完成了重命名的过程,当然我们还有很多重要的工作要做,比如如何获取HierarchicalDataTemplate中的TextBox控件这个是关键,其次TextBlock控件和TextBox控件必须同时绑定到同一属性,这样当属性值发生改变时,就能够更改TextBlock的Text属性值。

      注意:TextBox的默认绑定方式Mode=TwoWay。

      前端XAML代码,模板中加一个TextBlock控件和加一个TextBox控件:

    <TreeView.ItemTemplate>
           <HierarchicalDataTemplate DataType="{x:Type localex:TreeMode}" ItemsSource="{Binding Children}">
                <CheckBox Tag="{Binding Children}" IsChecked="{Binding IsChecked, Mode=TwoWay}" ToolTip="{Binding ToolTip}">
                   <StackPanel Orientation="Horizontal">
                       <Image VerticalAlignment="Center" Source="{Binding Icon}"/>
                          <StackPanel Orientation="Vertical">
                          <TextBlock Text="{Binding Name, Mode=TwoWay}" HorizontalAlignment="Center" Width="Auto"/>
                           <TextBox x:Name="renametextbox" Text="{Binding Name, Mode=TwoWay}" HorizontalAlignment="Center" Margin="0,-20,0,0"
                                 Width="Auto"  Visibility="Collapsed"  LostFocus="renametextbox_LostFous"/>
                           </StackPanel>
                     </StackPanel>
                  <CheckBox.ContextMenu>
                      <ContextMenu>
                         <MenuItem  Name="reNameItem" Header="重命名" Click="ReNameTreeViewItem_Click">                                              
                         </MenuItem>
                      </ContextMenu>
                   </CheckBox.ContextMenu>
                </CheckBox>                               
            </HierarchicalDataTemplate>
      </TreeView.ItemTemplate> 

      后端核心代码:

         //下面的部分是在鼠标指针位于此元素(TreeViewItem)上并且按下鼠标右键时发生。
            private void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
            {
                 //此处item定义的是一个类的成员变量,是一个TreeViewItem类型
                 item = GetParentObjectEx<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
                 if (item != null)
                  {
                     //使当前节点获得焦点
                     item.Focus();
    
                     //系统不再处理该操作
                     e.Handled = true;
                  }
            }
    
            //对当前TreeViewItem进行重命名
            private void ReNameTreeViewItem_Click(object sender, RoutedEventArgs e)
            {
                 //获取在TreeView.ItemTemplate中定义的TextBox控件
                 tempTextBox = FindVisualChild<TextBox>(item as DependencyObject);
                //设置该TextBox的Visibility 属性为Visible
                 tempTextBox.Visibility = Visibility.Visible;
            }

      下面的这个函数主要是利用VisualTreeHelper.GetParent()方法获取视觉树上面的各种控件,当我们鼠标点击TreeView节点的时候,我们沿着视觉树VisualTree依次向上查找获取相应的控件,在本例中依次查找到的控件为:TextBlock-》StackPanel-》StackPanel-》ContentPresenter-》BulletDecorator-》CheckBox-》ContentPresenter-》Boarder-》Grid-》TreeViewItem,通过每一次的向上查找最终找到我们需要的TreeViewItem对象。

          //获取当前TreeView的TreeViewItem
          public TreeViewItem GetParentObjectEx<TreeViewItem>(DependencyObject obj) where TreeViewItem : FrameworkElement
          {
              DependencyObject parent = VisualTreeHelper.GetParent(obj);
              while (parent != null)
              {
                  if (parent is TreeViewItem)
                  {
                      return (TreeViewItem)parent;
                  }
                  parent = VisualTreeHelper.GetParent(parent);
              }
              return null;
          }

      下面的这个函数也是非常重要的,由于我们定义的TextBox控件是在TreeView.ItemTemplate中定义的,所以无法通过this来查找当前的控件,如果无法获取当前的该控件,就无法进行下面的操作,所以这个函数也是非常重要的。和鼠标点击是沿着视觉树向上查找不同,此处我们需要沿着视觉树向下查找,直到找到我们TextBox控件为止,最终返回TextBox控件对象,这个刚好和上面的过程相反,但是这个过程也是非常重要的,具体的使用方式可以参考MSDN上面有更加具体的说明。

         //获取ItemTemplate内部的各种控件
            private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null && child is childItem)
                        return (childItem)child;
                    else
                    {
                        childItem childOfChild = FindVisualChild<childItem>(child);
                        if (childOfChild != null)
                            return childOfChild;
                    }
                }
                return null;
            }          
            //当TextBox失去焦点时发生此事件
            private void renametextbox_LostFous(object sender, RoutedEventArgs e)
            {
                tempTextBox.Visibility = Visibility.Collapsed;
            }
  • 相关阅读:
    1082 射击比赛 (20 分)
    1091 N-自守数 (15 分)
    1064 朋友数 (20 分)
    1031 查验身份证 (15 分)
    1028 人口普查 (20 分)
    1059 C语言竞赛 (20 分)
    1083 是否存在相等的差 (20 分)
    1077 互评成绩计算 (20 分)
    792. 高精度减法
    791. 高精度加法
  • 原文地址:https://www.cnblogs.com/xinaixia/p/5516237.html
Copyright © 2011-2022 走看看