Silverlight TreeView控件的增删改查
来自微软的Amit Dey提供了一个非常好的Sliverlight代码示例来展示了在Silverlight中树控件的增、删、改、查和拖放的功能。在Silverlight社区里面树控件的增、删、改、查是一个经常被问到的问题。但是我们收到还是有很多人请求得到这个代码示例。我们希望这个示例能够使开发人员轻松掌握这个典型的编程案例。
感谢Amit!
Silverlight TreeView控件的增删改查
http://deyamit.wordpress.com/2011/02/14/silverlight-treeview-control-with-crud/
这是一个Silverlight树控件增、删、改、查操作的示例。除了这个之外它还支持节点的拖放功能。这篇文章需要你最少对Silverlight和数据绑定有一点基本的了解。我们最后的输出效果会像这样显示:
数据
首先我们来看一下要绑定到TreeView控件的数据结构
Node是要绑定到每一个TreeViewItem的类
Text表示节点上的显示的数据
Children表示节点的子节点,注意Node类的继承
System.ComponentModel.INOtifyPropertyChanged类按顺序保持UI在异步操作。阅读这篇文章可以更好的理解这个功能。
另外注意Add和Delete这两个帮助函数,分别用来添加和删除节点。
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 的变化),TextBlock和TextBox绑定了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
>
后台代码
现在让我们先睹为快看一下用户控件的后台代码:
第一步,
鼠标的事件处理程序,TreeViewItem的MouseRightButtonUp事件做两件事情,给选定的节点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