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代碼(關鍵部分)

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

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM