代码改变世界

[译]Silverlight中TreeView增删改查和拖放

2011-03-04 00:59  Komici  阅读(3907)  评论(2编辑  收藏  举报

原文地址:http://deyamit.wordpress.com/2011/02/14/silverlight-treeview-control-with-crud/

翻译地址:http://blogs.msdn.com/b/codefx/archive/2011/02/15/silverlight-treeview-control-with-crud-and-drag-amp-drop.aspx

 

来自微软的Amit Dey提供了一个非常好的Sliverlight代码示例来展示了在Silverlight中树控件的增、删、改、查和拖放的功能。在Silverlight社区里面树控件的增、删、改、查是一个经常被问到的问题。但是我们收到还是有很多人请求得到这个代码示例。我们希望这个示例能够使开发人员轻松掌握这个典型的编程案例。

感谢Amit!

Silverlight TreeView控件的增删改查

这是一个Silverlight树控件增、删、改、查操作的示例。除了这个之外它还支持节点的拖放功能。这篇文章需要你最少对Silverlight和数据绑定有一点基本的了解。我们最后的输出效果会像这样显示:

blog

 

数据

首先我们来看一下要绑定到TreeView控件的数据结构

Node是要绑定到每一个TreeViewItem的类

Text表示节点上的显示的数据

Children表示节点的子节点,注意Node类的继承

System.ComponentModel.INOtifyPropertyChanged类按顺序保持UI在异步操作。阅读这篇文章可以更好的理解这个功能。

另外注意AddDelete这两个帮助函数,分别用来添加和删除节点。

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;


public class Node : INotifyPropertyChanged
{
    private String text;


    private ObservableCollection<Node> children;


    public event PropertyChangedEventHandler PropertyChanged;

 
    public ObservableCollection<Node> Children
    {
        get { return children; }
        set { children = value; }
    }


    public String Text
    {
        get { return text; }
        set { text = value; }
    }


    public Node(String text)
    {
        Children = new ObservableCollection<Node>();
        Text = text;
    }


    public void Add(Node node)
    {
        children.Add(node);
        NotifyPropertyChanged("Children");
    }


    public void Delete(Node node)
    {
        children.Remove(node);
        NotifyPropertyChanged("Children");
    }


    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

 

XAML

现在我们来看一下这个用户控件的XAML定义

第一步,我实现了一个右键菜单使增删改查更容易操作.你可以阅读这篇文章来学习右键菜单如何实现。

下一步,注意这两个HierarchicalDataTemplate一个是TreeViewItem 在查看状态(TextBlock的变化),另一个是编辑状态(TextBox 的变化),TextBlockTextBox绑定了Node的Text属性,我正在使用Silverlight Toolkitr的TreeViewDragDropTarget控件在父节点之间使用TreeViewItems进行拖放。

<UserControl
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
x:Class="CSSLTreeViewCRUDDragDrop.TreeViewCrudDragDrop"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
xmlns:mswindows="clr-namespace:Microsoft.Windows;assembly=System.Windows.Controls.Toolkit">
<UserControl.Resources>
<!-- Template for Edit mode of TreeViewItem -->
<sdk:HierarchicalDataTemplate x:Key="TreeViewMainEditTemplate" ItemsSource="{Binding Children}">
<TextBox Text="{Binding Text,Mode=TwoWay}" >
</TextBox>
</sdk:HierarchicalDataTemplate>
<!-- Template for Read mode for TreeViewItem -->
<sdk:HierarchicalDataTemplate x:Key="TreeViewMainReadTemplate"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Text,Mode=TwoWay}"
MouseRightButtonDown="TreeViewMain_MouseRightButtonDown"
MouseRightButtonUp="TreeViewMain_MouseRightButtonUp"
MouseLeftButtonDown="TreeViewMain_MouseLeftButtonDown" >
</TextBlock>
</sdk:HierarchicalDataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<!-- TreeViewDragDropTarget from Toolkit to add DragAndDrop feature -->
<toolkit:TreeViewDragDropTarget AllowDrop="True">
<!-- Custom TreeView  -->
<sdk:TreeView Name="TreeViewMain"
ItemTemplate="{StaticResource TreeViewMainReadTemplate}"
MouseRightButtonDown="TreeViewMain_MouseRightButtonDown"
MouseRightButtonUp="TreeViewMain_MouseRightButtonUp"
MouseLeftButtonDown="TreeViewMain_MouseLeftButtonDown"
Width="400" Height="400" >
</sdk:TreeView>
</toolkit:TreeViewDragDropTarget>
<!-- Context Menu -->
<Canvas>
<Popup Name="ContextMenu" Visibility="Collapsed">
<Border BorderThickness="1" BorderBrush="Black" Background="White">
<StackPanel>
<HyperlinkButton Content="Add" Name="AddButton" Click="AddButton_Click" />
<HyperlinkButton Content="Edit" Name="EditButton" Click="EditButton_Click"/>
<HyperlinkButton Content="Delete" Name="DeleteButton" Click="DeleteButton_Click"/>
</StackPanel>
</Border>
</Popup>
</Canvas>
</Grid>
</UserControl>

 

后台代码

现在让我们先睹为快看一下用户控件的后台代码:

第一步,鼠标的事件处理程序,TreeViewItemMouseRightButtonUp事件做两件事情,给选定的节点selectedNode分派指定的TreeViewItem数据上下文。

第二步,弹出右键菜单,选中节点selectedNode的信息是必需的,它作为引用被用来编辑TreeViewItem添加子节点到TreeViewItem和删除TreeViewItem

AddButton_Click事件处理程序,创建一个新的节点并当作节节点添加到选中的节点selecteNode的子节点下面。

EditButton_Click事件处理程序,改变选中节点的模板为编辑状态

DeleteButton_Click事件处理程序,首先确定TreeViewItem与选中的节点selectedNode关联,查找它的父节点,从父节点中删除选中的节点selectedNode。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections.ObjectModel;

namespace CSSLTreeViewCRUDDragDrop
{
    public partial class TreeViewCrudDragDrop : UserControl
    {
        ObservableCollection<Node> objectTree;

        Node selectedNode;

       public List<Node> Items
        {
            get
            {
                return objectTree.ToList<Node>();
            }
            set
            {
                objectTree = new ObservableCollection<Node>(value);
                TreeViewMain.ItemsSource = objectTree;
            }
        }

       public TreeViewCrudDragDrop()
        {
            InitializeComponent();
            objectTree = new ObservableCollection<Node>();
            TreeViewMain.ItemsSource = objectTree;
        }

       private void TreeViewMain_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            DisableEditForSelectedItem();

            e.Handled = true;
        }


       private void TreeViewMain_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            DisableEditForSelectedItem();

            if (sender is TextBlock)
            {
                selectedNode = (Node)((sender as TextBlock).DataContext);
            }
            else
            {
                selectedNode = null;
            }

            ShowContextMenu(e);
        }


       private void TreeViewMain_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DisableEditForSelectedItem();
            HideContextMenu();
        }


       private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            Node newNode = new Node("New Node");

            if (selectedNode != null)
            {
                selectedNode.Add(newNode);
            }
            else
            {
                if (objectTree != null)
                {
                    objectTree.Add(newNode);
                }
                else
                {
                    objectTree = new ObservableCollection<Node>();
                    objectTree.Add(newNode);
                }
            }

            HideContextMenu();
        }

       private void EditButton_Click(object sender, RoutedEventArgs e)
        {
            EnalbleEditForSelectedItem();

            TreeViewItem selectedTreeViewItem =


            TreeViewExtensions.GetContainerFromItem(TreeViewMain, selectedNode);


            HideContextMenu();
        }


       private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            TreeViewItem selectedTreeViewItem =
            TreeViewExtensions.GetContainerFromItem(TreeViewMain, selectedNode);

            if (selectedTreeViewItem != null)
            {
                TreeViewItem selectedTreeViewItemParent =
                TreeViewExtensions.GetParentTreeViewItem(selectedTreeViewItem);


                if (selectedTreeViewItemParent != null)
                {
                    Node seleactedParentNode = (Node)selectedTreeViewItemParent.DataContext;


                    seleactedParentNode.Delete(selectedNode);


                }
                else
                {
                    objectTree.Remove(selectedNode);
                }

          }


          HideContextMenu();
        }


       private void ShowContextMenu(MouseButtonEventArgs e)
        {
            e.Handled = true;
            Point p = e.GetPosition(this);
            ContextMenu.Visibility = Visibility.Visible;
            ContextMenu.IsOpen = true;
            ContextMenu.SetValue(Canvas.LeftProperty, (double)p.X);
            ContextMenu.SetValue(Canvas.TopProperty, (double)p.Y);
        }


       private void HideContextMenu()
        {
            ContextMenu.Visibility = Visibility.Collapsed;
            ContextMenu.IsOpen = false;
        }

       private void EnalbleEditForSelectedItem()
        {
            if (selectedNode != null)
            {
                SetTemplateForSelectedItem("TreeViewMainEditTemplate");
            }
        }


       private void DisableEditForSelectedItem()
        {
            if (selectedNode != null)
            {
                SetTemplateForSelectedItem("TreeViewMainReadTemplate");


                selectedNode = null;


            }
        }


       private void SetTemplateForSelectedItem(String templateName)
        {
            HierarchicalDataTemplate hdt = (HierarchicalDataTemplate)Resources[templateName];


            TreeViewItem selectedTreeViewItem =


            TreeViewExtensions.GetContainerFromItem(TreeViewMain, selectedNode);


            if (selectedTreeViewItem != null)


              selectedTreeViewItem.HeaderTemplate = hdt;
        }


    }


}

 

这样就完成了。

 

引用:

MichaelSnow : Silverlight Tip of the Day #3 – Mouse Right Clicks

MSDN : DataBinding Silverlight

Codeplex : Silverlight Toolkit

MSDN : INotifyPropertyChanged Interface

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
http://www.cnblogs.com/huazai/archive/2011/03/04/1970478.html