Silverlight Telerik控件学习:带CheckBox复选框的树形TreeView控件
在web开发中,带checkbox的tree是一个很有用的东东,比如权限选择、分类管理,如果不用sl,单纯用js+css实现是很复杂的,有了SL之后,就变得很轻松了
解决方案一:
利用Silvelright ToolKit(微软的开源项目),项目地址http://silverlight.codeplex.com/
在线演示地址:http://silverlight.net/content/samples/sl4/toolkitcontrolsamples/run/default.html
解决方案二:
telerik公司的Rad for Silverlight商业控件(收费控件)
不管用哪一种方案,代码都是差不多的,为了实现数据绑定,先创建一个silverlight类库项目BusinessObject,定义数据项实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Markup; namespace BusinessObject { /// <summary> /// 地区数据项 /// </summary> [ContentProperty( "Children" )] //指示Children属性是 XAML 的Content内容属性 public class PlaceItem : INotifyPropertyChanged { /// <summary> /// 构造函数 /// </summary> public PlaceItem() { Children = new Collection<PlaceItem>(); IsSelected = true ; } /// <summary> /// 地区名称 /// </summary> public string Name { get ; set ; } /// <summary> /// 地区描述 /// </summary> public string Description { get ; set ; } /// <summary> /// 得到下级元素容器 /// </summary> public Collection<PlaceItem> Children { get ; private set ; } /// <summary> /// 是否有子项 /// </summary> public bool HasChild { get { return Children.Count > 0; } } /// <summary> /// 是否选中 /// </summary> private bool ? _isSelected; /// <summary> /// 该特性是否想要被安装 /// </summary> public bool ? IsSelected { get { return _isSelected; } set { if (value != _isSelected) { _isSelected = value; OnPropertyChanged( "IsSelected" ); } } } public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 属性改变时触发事件 /// </summary> /// <param name="propertyName">Property that changed.</param> private void OnPropertyChanged( string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if ( null != handler) { handler.Invoke( this , new PropertyChangedEventArgs(propertyName)); } } } } |
然后再定义一个 演示数据集合类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Markup; namespace BusinessObject { /// <summary> /// 地区数据项 /// </summary> [ContentProperty( "Children" )] //指示Children属性是 XAML 的Content内容属性 public class PlaceItem : INotifyPropertyChanged { /// <summary> /// 构造函数 /// </summary> public PlaceItem() { Children = new Collection<PlaceItem>(); IsSelected = true ; } /// <summary> /// 地区名称 /// </summary> public string Name { get ; set ; } /// <summary> /// 地区描述 /// </summary> public string Description { get ; set ; } /// <summary> /// 得到下级元素容器 /// </summary> public Collection<PlaceItem> Children { get ; private set ; } /// <summary> /// 是否有子项 /// </summary> public bool HasChild { get { return Children.Count > 0; } } /// <summary> /// 是否选中 /// </summary> private bool ? _isSelected; /// <summary> /// 该特性是否想要被安装 /// </summary> public bool ? IsSelected { get { return _isSelected; } set { if (value != _isSelected) { _isSelected = value; OnPropertyChanged( "IsSelected" ); } } } public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 属性改变时触发事件 /// </summary> /// <param name="propertyName">Property that changed.</param> private void OnPropertyChanged( string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if ( null != handler) { handler.Invoke( this , new PropertyChangedEventArgs(propertyName)); } } } } |
好了,开始干正事儿了:
toolkit中的treeview用法
xaml部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | < UserControl x:Class="ToolKit.MainPage" 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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" xmlns:local="clr-namespace:BusinessObject;assembly=BusinessObject" xmlns:common="clr-namespace:System.Windows;assembly=System.Windows.Controls"> < Grid x:Name="LayoutRoot" Background="White"> < Grid.Resources > <!--定义数据源--> < local:SampleData x:Key="SampleDataSource"></ local:SampleData > <!--定义模板--> < common:HierarchicalDataTemplate x:Key="NodeTemplate" ItemsSource="{Binding Children}"> < StackPanel Orientation="Horizontal" ToolTipService.ToolTip="{Binding Description}"> < CheckBox IsTabStop="False" IsThreeState="{Binding HasChild}" IsChecked="{Binding IsSelected, Mode=TwoWay}" Click="ItemCheckbox_Click" /> < ContentPresenter Content="{Binding Name}" /> </ StackPanel > </ common:HierarchicalDataTemplate > </ Grid.Resources > < sdk:TreeView Name="treeView1" ItemTemplate="{StaticResource NodeTemplate}" ItemsSource="{Binding Source={StaticResource SampleDataSource}, Path=SamplePlaceItemCollection}" Margin="10" BorderThickness="0"> < sdk:TreeView.ItemContainerStyle > < Style TargetType="sdk:TreeViewItem"> <!--默认全展开--> < Setter Property="IsExpanded" Value="True"/> </ Style > </ sdk:TreeView.ItemContainerStyle > </ sdk:TreeView > </ Grid > </ UserControl > |
后端cs部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using BusinessObject; namespace ToolKit { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this .Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded( object sender, RoutedEventArgs e) { this .treeView1.ItemsSource = SampleData.SamplePlaceItemCollection; this .treeView1.ExpandAll(); //var obj = this.treeView1.Items[1]; } /// <summary> /// 点击节点时,选中子节点,同时设置父节点状态 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ItemCheckbox_Click( object sender, RoutedEventArgs e) { TreeViewItem item = GetParentTreeViewItem((DependencyObject)sender); if (item != null ) { PlaceItem feature = item.DataContext as PlaceItem; if (feature != null ) { UpdateChildrenCheckedState(feature); UpdateParentCheckedState(item); } } } /// <summary> /// 取得节点的父节点 /// </summary> /// <param name="item"></param> /// <returns></returns> private static TreeViewItem GetParentTreeViewItem(DependencyObject item) { if (item != null ) { DependencyObject parent = VisualTreeHelper.GetParent(item); TreeViewItem parentTreeViewItem = parent as TreeViewItem; return (parentTreeViewItem != null ) ? parentTreeViewItem : GetParentTreeViewItem(parent); } return null ; } /// <summary> /// 更新父节点的选中状态 /// </summary> /// <param name="item"></param> private static void UpdateParentCheckedState(TreeViewItem item) { //取得父节点 TreeViewItem parent = GetParentTreeViewItem(item); if (parent != null ) { PlaceItem parentItem = parent.DataContext as PlaceItem; if (parentItem != null ) { bool ? childrenCheckedState = parentItem.Children.First<PlaceItem>().IsSelected; for ( int i = 1; i < parentItem.Children.Count(); i++) { if (childrenCheckedState != parentItem.Children[i].IsSelected) { childrenCheckedState = null ; break ; } } parentItem.IsSelected = childrenCheckedState; //递归处理上级父节点 UpdateParentCheckedState(parent); } } } /// <summary> /// 更新子节点选中状态 /// </summary> /// <param name="feature"></param> private static void UpdateChildrenCheckedState(PlaceItem feature) { if (feature.IsSelected.HasValue) { foreach (PlaceItem childFeature in feature.Children) { childFeature.IsSelected = feature.IsSelected; if (childFeature.Children.Count() > 0) { UpdateChildrenCheckedState(childFeature); } } } } } } |
可以看到了,为了处理实现全选等功能,后端还是要写一些代码处理
telerik的treeview用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <UserControl x:Class= "Telerik.MainPage" 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:common= "clr-namespace:BusinessObject;assembly=BusinessObject" xmlns:telerik= "http://schemas.telerik.com/2008/xaml/presentation" > <Grid x:Name= "LayoutRoot" Background= "White" > <Grid.Resources> <common:SampleData x:Key= "SampleDataSource" ></common:SampleData> <!--数据节点模板--> <DataTemplate x:Key= "NodeTemplate" > <TextBlock Text= "{Binding Name}" /> </DataTemplate> <!--子节点模板--> <telerik:HierarchicalDataTemplate x:Key= "ChildTemplate" ItemTemplate= "{StaticResource NodeTemplate}" ItemsSource= "{Binding Children}" > <TextBlock Text= "{Binding Name}" /> </telerik:HierarchicalDataTemplate> <!--父节点模板--> <telerik:HierarchicalDataTemplate x:Key= "ParentTemplate" ItemTemplate= "{StaticResource ChildTemplate}" ItemsSource= "{Binding Children}" > <TextBlock Text= "{Binding Name}" /> </telerik:HierarchicalDataTemplate> </Grid.Resources> <telerik:RadTreeView ItemsSource= "{Binding Source={StaticResource SampleDataSource}, Path=SamplePlaceItemCollection}" ItemTemplate= "{StaticResource ParentTemplate}" SelectionMode= "Extended" IsLineEnabled= "True" ItemsOptionListType= "CheckList" IsOptionElementsEnabled= "True" IsRootLinesEnabled= "True" IsTriStateMode= "True" Margin= "10" > <telerik:RadTreeView.ItemContainerStyle> <Style TargetType= "telerik:RadTreeViewItem" > <!--默认全展开--> <Setter Property= "IsExpanded" Value= "True" /> </Style> </telerik:RadTreeView.ItemContainerStyle> </telerik:RadTreeView> </Grid> </UserControl> |
后端代码:木有!--商业控件,就是靠谱,很多功能已经帮开发者实现了.
效果:

作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!
2010-05-17 解决JQuery中的ready函数冲突
2010-05-17 C#检测SqlServer中某张表是否存在