zoukankan      html  css  js  c++  java
  • WPF/Silverlight HierarchicalDataTemplate 模版的使用

    上一篇 对Wpf/Silverlight Template 进行了总结,本篇继续上一篇,主要是介绍 HierarchicalDataTemplate 的使用方法。HierarchicalDataTemplate 继承于DataTemplate,被称之为"层级式数据模板",主要是应用层级比较明显数据集合,其典型的应用就是对TreeView控件进行数据绑定,接下来就在Silverlight 5 下进行一下演示。最近有个卖凉茶的节目比较火,叫中国好声音,里面的导师和其歌手的分组就是个层级结构,我们暂且先用它来做个例子吧。

    首先我们需要准备一下层级的数据集合,定义一个歌手类:

    歌手类
        /// <summary>
        /// 歌手类
        /// </summary>
        public class Singer
        {
            /// <summary>
            /// 歌手编号
            /// </summary>
            public int SingerId { get; set; }
    
            /// <summary>
            /// 歌手名称
            /// </summary>
            public string SingerName { get; set; }
    
            /// <summary>
            /// 歌手头像
            /// </summary>
            public string SingerHeader { get; set; }
        }

     然后定义一个 导师类,导师类中有个属性就是歌手的集合,代码如下:

    导师类
        /// <summary>
        /// 导师类
        /// </summary>
        public class Teacher
        {
            /// <summary>
            /// 导师编号
            /// </summary>
            public int TeacherId { get; set; }
    
            /// <summary>
            /// 导师名称
            /// </summary>
            public string TeacherName { get; set; }
    
            /// <summary>
            /// 导师头像
            /// </summary>
            public string TeacherHeader { get; set; }
    
            /// <summary>
            /// 学生列表
            /// </summary>
            public ObservableCollection<Singer> SingerList { get; set; }
        }

     接下来用代码组织一个导师与歌手的层级数据集合:

    好声音层级数据集合
        /// <summary>
        /// 好声音数据集合
        /// </summary>
        public class GoodVoice
        {
            public static ObservableCollection<Teacher> GoodVoiceData;
    
            static GoodVoice()
            {
                GoodVoiceData = new ObservableCollection<Teacher>();
                GoodVoiceData.Add(new Teacher()
                {
                    TeacherId = 1,
                    TeacherName = "刘欢",
                    TeacherHeader = @"Images/刘欢/刘欢.png",
                    SingerList = new ObservableCollection<Singer>()
                    {
                       new Singer(){ SingerId=1, SingerName="吉克隽逸",SingerHeader=@"Images/刘欢/吉克隽逸.png"},
                       new Singer(){ SingerId=2, SingerName="权振东",SingerHeader=@"Images/刘欢/权振东.png"},
                       new Singer(){ SingerId=3, SingerName="徐海星",SingerHeader=@"Images/刘欢/徐海星.png"},
                       new Singer(){ SingerId=4, SingerName="袁娅维",SingerHeader=@"Images/刘欢/袁娅维.png"},
                    }
                });
    
                GoodVoiceData.Add(new Teacher()
                {
                    TeacherId = 2,
                    TeacherName = "那英",
                    TeacherHeader = @"Images/那英/那英.png",
                    SingerList = new ObservableCollection<Singer>()
                    {
                       new Singer(){ SingerId=5, SingerName="张炜",SingerHeader=@"Images/那英/张炜.png"},
                       new Singer(){ SingerId=6, SingerName="梁博",SingerHeader=@"Images/那英/梁博.png"},
                       new Singer(){ SingerId=7, SingerName="张赫宣",SingerHeader=@"Images/那英/张赫宣.png"},
                       new Singer(){ SingerId=8, SingerName="多亮",SingerHeader=@"Images/那英/多亮.png"},
                    }
                });
    
                GoodVoiceData.Add(new Teacher()
                {
                    TeacherId = 3,
                    TeacherName = "杨坤",
                    TeacherHeader = @"Images/杨坤/杨坤.png",
                    SingerList = new ObservableCollection<Singer>()
                    {
                       new Singer(){ SingerId=9, SingerName="金志文",SingerHeader=@"Images/杨坤/金志文.png"},
                       new Singer(){ SingerId=10, SingerName="关喆",SingerHeader=@"Images/杨坤/关喆.png"},
                       new Singer(){ SingerId=11, SingerName="平安",SingerHeader=@"Images/杨坤/平安.png"},
                       new Singer(){ SingerId=12, SingerName="丁丁",SingerHeader=@"Images/杨坤/丁丁.png"},
                    }
                });
    
                GoodVoiceData.Add(new Teacher()
                {
                    TeacherId = 4,
                    TeacherName = "庾澄庆",
                    TeacherHeader = @"Images/庾澄庆/庾澄庆.png",
                    SingerList = new ObservableCollection<Singer>()
                    {
                       new Singer(){ SingerId=9, SingerName="金池",SingerHeader=@"Images/庾澄庆/金池.png"},
                       new Singer(){ SingerId=10, SingerName="王韵壹",SingerHeader=@"Images/庾澄庆/王韵壹.png"},
                       new Singer(){ SingerId=11, SingerName="吴莫愁",SingerHeader=@"Images/庾澄庆/吴莫愁.png"},
                       new Singer(){ SingerId=12, SingerName="大山",SingerHeader=@"Images/庾澄庆/大山.png"},
                    }
                });
            }
        }

     有了数据集合,我们就可以在Xaml中编写我们的 HierarchicalDataTemplate 模版了,我们定义两个模版,一个TeacherTemplate 代表导师节点,一个SingerTemplate 代表歌手节点,并把TeacherTemplate中的ItemTemplate指定为SingerTemplate,具体代码如下: 

    <common:HierarchicalDataTemplate x:Key="SingerTemplate">        
            <StackPanel Orientation="Horizontal" Height="24">
                <Image Source="{Binding SingerHeader}" Height="24" Width="24"/>
                <TextBlock Text="{Binding SingerName}" Margin="2,0,0,0" VerticalAlignment="Center" FontSize="12" Foreground="Green" />           
            </StackPanel>
    </common:HierarchicalDataTemplate>
        
    <common:HierarchicalDataTemplate x:Key="TeacherTemplate" ItemsSource="{Binding SingerList}" ItemTemplate="{StaticResource SingerTemplate}">
            <StackPanel Orientation="Horizontal" Height="24">
                <Image Source="{Binding TeacherHeader}" Height="24" Width="24" />
                <TextBlock Text="{Binding TeacherName}" Margin="2,0,0,0" HorizontalAlignment="Center"  FontSize="14" Foreground="Blue"/>
            </StackPanel>
    </common:HierarchicalDataTemplate>

     在Silverlight下,需要在Xaml代码中添加如下命名空间:xmlns:common="clr-namespace:System.Windows;assembly=System.Windows.Controls" 

    在此之后,在主界面MainPage.xaml 中添加一个TreeView控件,并给该控件增加一个根节点,命名为 RootItem,并把该根节点的ItemTemplate指定为我们刚刚编写的层级模版中的 TeacherTemplate:

    <sdk:TreeView x:Name="GoodVoiceTree" Width="200" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch">
        <sdk:TreeViewItem x:Name="RootItem" ItemTemplate="{StaticResource TeacherTemplate}" IsExpanded="True">
             <sdk:TreeViewItem.HeaderTemplate>
                  <DataTemplate>
                     <StackPanel Orientation="Horizontal">
                        <Image Source="images/中国好声音.png" Height="24" Width="24"/>
                        <TextBlock Text="中国好声音" Margin="2,0,0,0" VerticalAlignment="Center" FontSize="16" Foreground="Red" />
                     </StackPanel>
                  </DataTemplate>
             </sdk:TreeViewItem.HeaderTemplate>
       </sdk:TreeViewItem>
    </sdk:TreeView>

     接下来,我们为该树控件的根节点RootItem绑定我们的数据集合就可以展现我们的树形控件了:

    this.RootItem.ItemsSource = GoodVoice.GoodVoiceData;

     运行结果如下图:

    其实在我们的实际开发项目中有些数据的层级结构是固定的,比如上面的例子,就固定了导师和歌手两个层级,固定的层级的话我们可以对每一层的样式方便的进行控制(直接在每层的模版中制作就可以)。但还有很多的时候,数据的层级是不固定的,我们也来进行一下简单的演示:

    首先定义个TreeNode类,代表每层的数据模型:

    TreeNode 代码
        public class TreeNode
        {
            /// <summary>
            /// 节点名称
            /// </summary>
            public string  NodeName { get; set; }
    
            /// <summary>
            /// 节点图片
            /// </summary>
            public string NodeImage { get; set; }
    
            /// <summary>
            /// 是否展开
            /// </summary>
            public bool IsOpen { get; set; }
    
            /// <summary>
            /// 子节点
            /// </summary>
            public ObservableCollection<TreeNode> ChildNode { get; set; }
        }

     同样用代码组织一个层级数据集合:

    TreeNodeData
        public class TreeNodeData
        {
            public static ObservableCollection<TreeNode> TreeNodeList;
            
            static TreeNodeData()
            {
                TreeNodeList = new ObservableCollection<TreeNode>();
                //根节点
                TreeNode RootNode = new TreeNode()
                {
                    NodeName = "根节点",
                    NodeImage = @"Images/Tree/Root.png",
                    IsOpen = true,
                    ChildNode = new ObservableCollection<TreeNode>()               
                };
    
                //子节点A
                TreeNode Node_A = new TreeNode()
                {
                    NodeName = "子节点A",
                    NodeImage = @"Images/Tree/Node.png",
                    IsOpen = false,
                    ChildNode = new ObservableCollection<TreeNode>()
                };
                Node_A.ChildNode.Add(new TreeNode() { NodeName = "叶子节点A-1", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
                Node_A.ChildNode.Add(new TreeNode() { NodeName = "叶子节点A-2", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
                Node_A.ChildNode.Add(new TreeNode() { NodeName = "叶子节点A-3", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
                
                //子节点B
                TreeNode Node_B = new TreeNode()
                {
                    NodeName = "子节点B",
                    NodeImage = @"Images/Tree/Node.png",
                    IsOpen = true,
                    ChildNode = new ObservableCollection<TreeNode>()
                };
                Node_B.ChildNode.Add(new TreeNode() { NodeName = "叶子节点B-1", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
                Node_B.ChildNode.Add(new TreeNode() { NodeName = "叶子节点B-2", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
    
                //节点B 子节点B-3
                TreeNode Node_B_3 = new TreeNode()
                {
                    NodeName = "子节点B-3",
                    NodeImage = @"Images/Tree/SubNode.png",
                    IsOpen = false,
                    ChildNode = new ObservableCollection<TreeNode>()
                };
                Node_B_3.ChildNode.Add(new TreeNode() { NodeName = "叶子节点B-3-1", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
                Node_B_3.ChildNode.Add(new TreeNode() { NodeName = "叶子节点B-3-2", NodeImage = @"Images/Tree/Leaf.png", IsOpen = false });
    
                Node_B.ChildNode.Add(Node_B_3);         
                RootNode.ChildNode.Add(Node_A);
                RootNode.ChildNode.Add(Node_B);
    
                TreeNodeList.Add(RootNode);
                
            }
        }

    在Xaml中编写的层级模版:

    <common:HierarchicalDataTemplate x:Key="TreeNodeTemplate" ItemsSource="{Binding ChildNode}" >
        <StackPanel Orientation="Horizontal" Height="24">
            <Image Source="{Binding NodeImage}" Height="24" Width="24" />
            <TextBlock Text="{Binding NodeName}" Margin="2,0,0,0" HorizontalAlignment="Center"  FontSize="12" Foreground="Blue"/>
        </StackPanel>
    </common:HierarchicalDataTemplate>

    在这里我们需要注意一个问题:我们在TreeNode类的时候定义个一个布尔值属性 IsOpen,就是利用这个属性来控制我们这棵树的节点的展开闭合状态的:True 代表该节点展开,False 代表该节点闭合。如果不这么做我们对 TreeView控件进行绑定后,树的初始状态都是闭合的,但是这种方法仅限于WPF 和 Silverlight 5 ,Silverlight4 及以下版本是不灵滴,不知道是不是Silverlight的一个Bug。

    <sdk:TreeView x:Name="MyTree" Width="200" Grid.Row="1" Grid.Column="1"  ItemTemplate="{StaticResource TreeNodeTemplate}"            
                          HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch">
            <sdk:TreeView.ItemContainerStyle>
                <Style TargetType="sdk:TreeViewItem">
                     <Setter Property="IsExpanded" Value="{Binding IsOpen}"/>
                </Style>
            </sdk:TreeView.ItemContainerStyle>           
    </sdk:TreeView>

     这里我们就利用了上一篇提到的TreeView的ItemContainerStyle属性,对TreeView中的所有TreeviewItem的IsExpander属性进行了绑定。

    同样将我们的数据集合绑定到我们的这个TreeView控件上: 

    this.MyTree.ItemsSource = TreeNodeData.TreeNodeList;

     由于我们在数据集合中对 根节点 和 子节点B 的IsOpen属性设置为了True,因此这两个节点是展开的,运行结果如下图:

    至此,在Silverlight下利用HierarchicalDataTemplate 层级模版绑定TreeView控件的使用方式,演示完毕,至于如何获取TreeView 节点的数据,我们可以在TreeView控件中的SelectedItemChanged事件中进行获取,这里就不贴代码了,大家可以下载源码参看。

    源码下载

  • 相关阅读:
    Activiti Model Editor组件
    Activiti 5.17 实体对象与类和数据库表的映射
    工作流入门链接
    揭秘jbpm流程引擎内核设计思想及构架
    比较Activiti中三种不同的表单及其应用
    Activiti源码分析
    Spring Security教程(5)---- 国际化配置及UserCache
    spring DelegatingFilterProxy管理过滤器
    Apache 处理svg工具包Apache(tm) Batik SVG Toolkit
    Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/lxblog/p/2737876.html
Copyright © 2011-2022 走看看