实际开发中控件的数据源肯定是动态绑定的,不可能在xaml里写死item项。既然要绑定,就先来几个实体类:
上面是类图,各类的代码如下:
BusinessBaseObject
using System.ComponentModel; namespace BusinessObject { public class BusinessBaseObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 属性改变时触发事件 /// </summary> /// <param name="propertyName">Property that changed.</param> protected void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } }
SelectedItemBase
using System.Collections.ObjectModel; using System.Windows.Markup; namespace BusinessObject { [ContentProperty("Children")]//指示Children属性是 XAML 的Content内容属性 public class SelectedItemBase:BusinessBaseObject { public SelectedItemBase() { Children = new Collection<SelectedItemBase>(); IsSelected = true; } /// <summary> /// 得到下级元素容器 /// </summary> public Collection<SelectedItemBase> 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"); } } } } }
NodeItem 主要用于treeview中的节点数据展示
using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Markup; namespace BusinessObject { /// <summary> /// 地区数据项 /// </summary> public class NodeItem : SelectedItemBase { /// <summary> /// 构造函数 /// </summary> public NodeItem() { Text = ""; Value = ""; Description = ""; ImageUri = "/Common.Silverlight.Resource;component/img/Book.png"; } /// <summary> /// 节点文本 /// </summary> public string Text { get; set; } /// <summary> /// 节点值 /// </summary> public string Value { set; get; } /// <summary> /// 节点描述 /// </summary> public string Description { get; set; } /// <summary> /// 节点图象 /// </summary> public string ImageUri { get; set; } } }
MenuItem 主要用于菜单项展示
namespace BusinessObject { public class MenuItem:NodeItem { public MenuItem() { NavigateUri = ""; ImageUri = "/Common.Silverlight.Resource;component/img/Book_Open.png"; } /// <summary> /// 菜单点击后的链接地址 /// </summary> public string NavigateUri { set; get; } } }
SampleData生成示例数据集合
using System.Collections.ObjectModel; namespace BusinessObject { public class SampleData { private static ObservableCollection<NodeItem> _samplePlaceItemCollection; private static ObservableCollection<MenuItem> _sampleMenuItemCollection; public SampleData() { } static SampleData() { #region 地区演示数据 _samplePlaceItemCollection = new ObservableCollection<NodeItem>(); NodeItem ShangHai = new NodeItem() { Text = "上海市", IsSelected = false, ImageUri = "/Common.Silverlight.Resource;component/img/Home.png" }; ShangHai.Children.Add(new NodeItem() { Text = "黄浦区", IsSelected = false }); ShangHai.Children.Add(new NodeItem() { Text = "闵行区", IsSelected = false }); ShangHai.Children.Add(new NodeItem() { Text = "徐汇区", IsSelected = false }); NodeItem HuBei = new NodeItem() { Text = "湖北省", IsSelected = null, ImageUri = "/Common.Silverlight.Resource;component/img/Book_Open.png" }; NodeItem WuHan = new NodeItem() { Text = "武汉市", ImageUri = "/Common.Silverlight.Resource;component/img/MSN.png" }; WuHan.Children.Add(new NodeItem() { Text = "汉口区" }); WuHan.Children.Add(new NodeItem() { Text = "汉阳区" }); WuHan.Children.Add(new NodeItem() { Text = "武昌区", IsSelected = false, ImageUri = "/Common.Silverlight.Resource;component/img/Computer.png" }); HuBei.Children.Add(WuHan); HuBei.Children.Add(new NodeItem() { Text = "孝感市" }); _samplePlaceItemCollection.Add(ShangHai); _samplePlaceItemCollection.Add(HuBei); #endregion #region _sampleMenuItemCollection = new ObservableCollection<MenuItem>(); MenuItem itemBasic = new MenuItem() { Text = "基础数据", IsSelected = true, ImageUri = "/Common.Silverlight.Resource;component/img/Computer.png" }; itemBasic.Children.Add(new MenuItem() { Text = "部门管理", NavigateUri="Basic/Department.xap" }); itemBasic.Children.Add(new MenuItem() { Text = "员工管理", NavigateUri="Basic/Employee.xap" }); itemBasic.Children.Add(new MenuItem() { Text = "menu001", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemBasic.Children.Add(new MenuItem() { Text = "menu002", NavigateUri = "Plan/FFM.xap" }); itemBasic.Children.Add(new MenuItem() { Text = "menu003", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemBasic.Children.Add(new MenuItem() { Text = "menu004", NavigateUri = "Plan/FFM.xap" }); itemBasic.Children.Add(new MenuItem() { Text = "menu005", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemBasic.Children.Add(new MenuItem() { Text = "menu006", NavigateUri = "Plan/FFM.xap" }); itemBasic.Children.Add(new MenuItem() { Text = "menu007", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemBasic.Children.Add(new MenuItem() { Text = "menu008", NavigateUri = "Plan/FFM.xap" }); MenuItem itemMsg = new MenuItem() { Text = "报文管理", IsSelected=false, ImageUri = "/Common.Silverlight.Resource;component/img/Home.png" }; itemMsg.Children.Add(new MenuItem() { Text = "FFM报文计划", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemMsg.Children.Add(new MenuItem() { Text = "FSU报文计划", NavigateUri = "Plan/FFM.xap" }); itemMsg.Children.Add(new MenuItem() { Text = "menu001", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemMsg.Children.Add(new MenuItem() { Text = "menu002", NavigateUri = "Plan/FFM.xap" }); itemMsg.Children.Add(new MenuItem() { Text = "menu003", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemMsg.Children.Add(new MenuItem() { Text = "menu004", NavigateUri = "Plan/FFM.xap" }); itemMsg.Children.Add(new MenuItem() { Text = "menu005", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemMsg.Children.Add(new MenuItem() { Text = "menu006", NavigateUri = "Plan/FFM.xap" }); itemMsg.Children.Add(new MenuItem() { Text = "menu007", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemMsg.Children.Add(new MenuItem() { Text = "menu008", NavigateUri = "Plan/FFM.xap" }); MenuItem itemOther = new MenuItem() { Text = "系统管理", IsSelected=false, ImageUri = "/Common.Silverlight.Resource;component/img/MSN.png" }; itemOther.Children.Add(new MenuItem() { Text = "系统日志", NavigateUri = "Event/FFM.xap" }); itemOther.Children.Add(new MenuItem() { Text = "退出登录", NavigateUri = "Plan/MSN.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemOther.Children.Add(new MenuItem() { Text = "menu001", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemOther.Children.Add(new MenuItem() { Text = "menu002", NavigateUri = "Plan/FFM.xap" }); itemOther.Children.Add(new MenuItem() { Text = "menu003", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemOther.Children.Add(new MenuItem() { Text = "menu004", NavigateUri = "Plan/FFM.xap" }); itemOther.Children.Add(new MenuItem() { Text = "menu005", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemOther.Children.Add(new MenuItem() { Text = "menu006", NavigateUri = "Plan/FFM.xap" }); itemOther.Children.Add(new MenuItem() { Text = "menu007", NavigateUri = "Plan/FFM.xap", ImageUri = "/Common.Silverlight.Resource;component/img/Book.png" }); itemOther.Children.Add(new MenuItem() { Text = "menu008", NavigateUri = "Plan/FFM.xap" }); _sampleMenuItemCollection.Add(itemBasic); _sampleMenuItemCollection.Add(itemMsg); _sampleMenuItemCollection.Add(itemOther); #endregion } public static ObservableCollection<NodeItem> SamplePlaceItemCollection { get { return _samplePlaceItemCollection; } } public static ObservableCollection<MenuItem> SampleMenuItemCollection { get { return _sampleMenuItemCollection; } } } }
TreeView、ContextMenu
为了将NoteItem中的IsSelected属性在绑定时自动转换成CheckBox的CheckState,需要写一个转换器
using System; using System.Windows.Automation; using System.Windows.Data; namespace Common.Silverlight { public class BooleanToCheckStateConvertor : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { bool? isSelected = (bool?)value; ToggleState result = ToggleState.Off; if (isSelected.HasValue == false) { result = ToggleState.Indeterminate; } else if (isSelected.Value) { result = ToggleState.On; } return result; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { ToggleState state = (ToggleState)value; bool? result = null; switch (state) { case ToggleState.Indeterminate: result = null; break; case ToggleState.Off: result = false; break; case ToggleState.On: result = true; break; default: break; } return result; } } }
然后需要定义数据模板,如果需要右键弹出菜单,也一并加在里面
<UserControl x:Class="Telerik.Sample.TreeView" 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:model="clr-namespace:BusinessObject;assembly=BusinessObject" xmlns:common="clr-namespace:Common.Silverlight;assembly=Common.Silverlight" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.Resources> <telerik:ContainerBindingCollection x:Name="BindingsCollection"> <!--用于将节点的选中状态,与数据项的IsSelected绑定--> <telerik:ContainerBinding PropertyName="CheckState" Binding="{Binding IsSelected,Converter={StaticResource BooleanToCheckStateConvertor}, Mode=TwoWay}" /> <!--将节点图象与数据项的ImageUri绑定--> <telerik:ContainerBinding PropertyName="DefaultImageSrc" Binding="{Binding ImageUri}" /> </telerik:ContainerBindingCollection> <!--数据节点模板--> <DataTemplate x:Key="NodeTemplate" telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"> <TextBlock Text="{Binding Text}" /> </DataTemplate> <!--子节点模板--> <telerik:HierarchicalDataTemplate x:Key="ChildTemplate" ItemTemplate="{StaticResource NodeTemplate}" ItemsSource="{Binding Children}" telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"> <TextBlock Text="{Binding Text}" /> </telerik:HierarchicalDataTemplate> <!--父节点模板--> <telerik:HierarchicalDataTemplate x:Key="ParentTemplate" ItemTemplate="{StaticResource ChildTemplate}" ItemsSource="{Binding Children}" telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"> <TextBlock Text="{Binding Text}" /> </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:RadContextMenu.ContextMenu> <telerik:RadContextMenu x:Name="ContextMenu1" ItemClick="ContextMenuClick" Opened="ContextMenuOpened"> <telerik:RadMenuItem Header="添加" Tag="Add" /> <telerik:RadMenuItem Header="删除" Tag="Delete" /> <telerik:RadMenuItem Header="修改" Tag="Edit" /> <telerik:RadMenuItem IsSeparator="True" /> <telerik:RadMenuItem Header="设置菜单权限" Tag="MenuRight" /> <telerik:RadMenuItem Header="设置数据范围" Tag="DataRange" /> </telerik:RadContextMenu> </telerik:RadContextMenu.ContextMenu> </telerik:RadTreeView> </Grid> </UserControl>
这里面用到了几个资源,定义在全局App.Xaml里
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Telerik.App" xmlns:model ="clr-namespace:BusinessObject;assembly=BusinessObject" xmlns:common ="clr-namespace:Common.Silverlight;assembly=Common.Silverlight" > <Application.Resources> <!--示例数据源--> <model:SampleData x:Key="SampleDataSource"></model:SampleData> <!--转换器:用于bool?转换成CheckBox的三种选中状态--> <common:BooleanToCheckStateConvertor x:Key="BooleanToCheckStateConvertor"></common:BooleanToCheckStateConvertor> </Application.Resources> </Application>
右键弹出菜单点击后,我们需要知道是在哪个节点上弹出的,以及我们选择了哪个菜单项,需要一些后端处理代码
using System.Windows; using System.Windows.Controls; using BusinessObject; using Telerik.Windows.Controls; namespace Telerik.Sample { public partial class TreeView : UserControl { NodeItem selectedNodeItem = null; public TreeView() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { //this.RadTreeView1.ItemsSource = SampleData.SamplePlaceItemCollection; } /// <summary> /// 菜单弹出后,点击具体菜单项时触发 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ContextMenuClick(object sender, Windows.RadRoutedEventArgs e) { var origin_src = e.OriginalSource as RadMenuItem; //反馈操作结果 DialogParameters pars = new DialogParameters(); pars.Header = "信息"; pars.Content = string.Format("你选择的菜单是:\n{0},{1}\n\n当前节点为:{2}\n{3}", origin_src.Header.ToString(), origin_src.Tag.ToString(), selectedNodeItem.Text,selectedNodeItem.ImageUri); RadWindow.Alert(pars); selectedNodeItem = null; } /// <summary> /// 菜单弹出时触发 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ContextMenuOpened(object sender, RoutedEventArgs e) { RadTreeViewItem item = this.ContextMenu1.GetClickedElement<RadTreeViewItem>(); if (item != null) { selectedNodeItem = item.DataContext as NodeItem; } } } }
运行效果图:
选择一个弹出菜单项后的效果:
PanelBar的Accordion效果
<UserControl x:Class="Telerik.Sample.Accordion" 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:telerik="http://schemas.telerik.com/2008/xaml/presentation"> <Grid> <Grid.Resources> <telerik:ContainerBindingCollection x:Name="BindingsCollection"> <!--用于将工作间组的展开状态,与数据项的IsSelected绑定--> <telerik:ContainerBinding PropertyName="IsExpanded" Binding="{Binding IsSelected, Mode=TwoWay}" /> </telerik:ContainerBindingCollection> <!--菜单项模板--> <telerik:HierarchicalDataTemplate x:Key="ChildTemplate"> <StackPanel> <Image Source="{Binding ImageUri}" Width="48" Height="48"></Image> <TextBlock Text="{Binding Text}" Margin="0,5,0,0" TextAlignment="Center"></TextBlock> </StackPanel> </telerik:HierarchicalDataTemplate> <!--菜单组模板--> <telerik:HierarchicalDataTemplate x:Key="ParentTemplate" ItemTemplate="{StaticResource ChildTemplate}" ItemsSource="{Binding Children}" telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"> <StackPanel Orientation="Horizontal"> <Image Source="{Binding ImageUri}" Width="24" Height="24" Margin="5,0,5,0"></Image> <TextBlock Text="{Binding Text}" Margin="0,2,0,0" FontSize="14" FontWeight="Bold"></TextBlock> </StackPanel> </telerik:HierarchicalDataTemplate> </Grid.Resources> <telerik:RadPanelBar Background="White" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" ExpandMode="Single" Width="150" ItemTemplate="{StaticResource ParentTemplate}" ItemsSource="{Binding Source={StaticResource SampleDataSource}, Path=SampleMenuItemCollection}"> <!--<telerik:RadPanelBarItem IsExpanded="True" Header="基础数据" > <StackPanel> <telerik:RadButton Margin="0,3"> <StackPanel> <Image Source="/Common.Silverlight.Resource;component/img/Book.png" Width="64" Height="64" ></Image> <TextBlock TextAlignment="Center">部门管理</TextBlock> </StackPanel> </telerik:RadButton> <telerik:RadButton Margin="0,3"> <StackPanel> <Image Source="/Common.Silverlight.Resource;component/img/Book_Open.png" Width="64" Height="64" ></Image> <TextBlock TextAlignment="Center" Text="adfasdfasdf"/> </StackPanel> </telerik:RadButton> </StackPanel> </telerik:RadPanelBarItem> <telerik:RadPanelBarItem Header="报文管理"> <StackPanel> <telerik:RadButton Content="FFM报文计划" /> <telerik:RadButton Content="FSU报文计划" /> </StackPanel> </telerik:RadPanelBarItem>--> </telerik:RadPanelBar> </Grid> </UserControl>
运行时截图:
TabPanel+Frame
为了节省空间,将多个界面以Tab标签页方式整合在一起是常见的用法,每个标签页的内容通常是实例化一个单独的Xaml模块,可以考虑每个标签页的内容以Frame形式嵌入一个xaml
<UserControl x:Class="Telerik.SampleIndex" 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:local="clr-namespace:Telerik.Sample" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"> <Grid > <telerik:RadTabControl DisplayMemberPath="Content" ScrollMode="Viewport" BorderThickness="0"> <telerik:RadTabItem Header="测试Tab" IsSelected="True"> <telerik:RadTabItem.Content> <telerik:RadTreeView IsLineEnabled="True" ItemsOptionListType="CheckList" IsOptionElementsEnabled="True"> <telerik:RadTreeViewItem Header="中国航信" IsExpanded="True" DefaultImageSrc="/Common.Silverlight.Resource;component/img/Book_Open.png" > <telerik:RadTreeViewItem Header="天信达" DefaultImageSrc="/Common.Silverlight.Resource;component/img/Book.png"> </telerik:RadTreeViewItem> </telerik:RadTreeViewItem> </telerik:RadTreeView> </telerik:RadTabItem.Content> </telerik:RadTabItem> <telerik:RadTabItem Header="TreeView"> <telerik:RadTabItem.Content> <telerik:RadFrame HorizontalAlignment="Left" x:Name="radFrame1" VerticalAlignment="Top" > <local:TreeView/> </telerik:RadFrame> </telerik:RadTabItem.Content> </telerik:RadTabItem> <telerik:RadTabItem Header="Accordion"> <telerik:RadTabItem.Content> <telerik:RadFrame HorizontalAlignment="Left" x:Name="radFrame2" VerticalAlignment="Top" > <local:Accordion/> </telerik:RadFrame> </telerik:RadTabItem.Content> </telerik:RadTabItem> </telerik:RadTabControl> </Grid> </UserControl>