效果图

前台代码

<UserControl x:Class="Hotellight.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"
    xmlns:local="clr-namespace:Hotellight"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
             
                <ResourceDictionary>
                    <!-- Put all the items inside a horizontally stacked panel -->
                    <ItemsPanelTemplate x:Key="ItemsPanel">
                        <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
                    </ItemsPanelTemplate>

<!-- TreeViewItem style to stack a header on top of children -->
                    <Style x:Key="ContainerStyle" TargetType="sdk:TreeViewItem">
                        <Setter Property="ItemsPanel" Value="{StaticResource ItemsPanel}"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="sdk:TreeViewItem">
                                    <StackPanel  VerticalAlignment="Top" HorizontalAlignment="Stretch">
                                        <Canvas>
                                            <Line X1="0" Y1="0" X2="0" Y2="0" StrokeDashArray="2 4" Stroke="#88444444" StrokeThickness="1" local:TreeViewItemConnectingLine.IsSingleConnectingLineOf="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneTime}"></Line>
                                        </Canvas>
                                        <ContentControl local:TreeViewItemConnectingLine.IsHeaderOf="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneTime}"
                                                            x:Name="HeaderContent"
                                                        Content="{TemplateBinding Header}"
                                                        ContentTemplate="{TemplateBinding HeaderTemplate}"
                                                        HorizontalAlignment="Center"
                                                        HorizontalContentAlignment="Center"
                                                        VerticalAlignment="Center"/>

<ItemsPresenter Canvas.Left="100" Canvas.Top="80" x:Name="Items" VerticalAlignment="Top" HorizontalAlignment="Center"/>

</StackPanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>

<!-- HeaderContent -->
                    <sdk:HierarchicalDataTemplate x:Key="DepartmentTemplate" ItemsSource="{Binding ChildNodes}" ItemContainerStyle="{StaticResource ContainerStyle}">
                        <Border Background="AliceBlue" Margin="4 8" Padding="2" BorderBrush="Blue" BorderThickness="1" CornerRadius="6">
                            <StackPanel HorizontalAlignment="Stretch">
                                <TextBlock  Text="{Binding Entity.Name}" Margin="6 4" HorizontalAlignment="Center" FontSize="12" FontWeight="Bold"/>
                            </StackPanel>
                        </Border>
                    </sdk:HierarchicalDataTemplate>

</ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
           
        </ResourceDictionary>

</UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:TreeView    ItemTemplate="{StaticResource DepartmentTemplate}"
                        ItemsPanel="{StaticResource ItemsPanel}"
                      ItemContainerStyle="{StaticResource ContainerStyle}"
                        ItemsSource="{Binding}">
          
        </sdk:TreeView>
    </Grid>
</UserControl>

数据类

View Code

  1   public class TreeNode<T> : GalaSoft.MvvmLight.ViewModelBase  2         where T:new()  3     {  4         private T _entity;  5         public T Entity  6         {  7             get  8             {  9                 return _entity; 10             } 11             internal set 12             { 13                 _entity = value; 14                 RaisePropertyChanged("Entity"); 15  16             } 17         } 18         private int _level=-1; 19         public int Level 20         { 21             get { 22                 return _level; 23             } 24             set { 25                 if (_level != value) 26                 { 27                     _level = value; 28                     RaisePropertyChanged("Level"); 29                 } 30             } 31         } 32         public TreeNode(T entity) 33         { 34             Entity = entity; 35             _childNode = new ObservableCollection<TreeNode<T>>(); 36         } 37         private TreeNode<T> _parent; 38         public TreeNode<T> Parent 39         { 40             get 41             { 42                 return _parent; 43             } 44             set 45             { 46                 if (_parent != value) 47                 { 48                     _parent = value; 49                     RaisePropertyChanged("Parent"); 50                 } 51             } 52         } 53         private TreeNode<T> _nextNode; 54          55         public TreeNode<T> NextNode 56         { 57             get { 58                 return _nextNode; 59             } 60             internal set { 61                 if (_nextNode != value) 62                 { 63                     _nextNode = value; 64                     RaisePropertyChanged("NextNode"); 65                 } 66             } 67         } 68         private TreeNode<T> _previouNode; 69          70         public TreeNode<T> PreviouNode 71         { 72             get { 73                 return _previouNode; 74             } 75             internal set { 76                 if (_previouNode != value) 77                 { 78                     _previouNode = value; 79                     RaisePropertyChanged("PreviouNode"); 80                 } 81             } 82         } 83         private ObservableCollection<TreeNode<T>> _childNode; 84         public ObservableCollection<TreeNode<T>> ChildNodes 85         { 86             get 87             { 88                 return _childNode; 89             } 90             internal set 91             { 92                 _childNode = value; 93                 RaisePropertyChanged("ChildNodes"); 94             } 95         } 96     } 97     public class TreeCollection<T> : ObservableCollection<TreeNode<T>> 98         where T:new() 99     {100         public const string DefaultKeyProperty = "ID";101         public const string DefaultReferenceProperty = "ParentID";102         internal  PropertyInfo KeyProperty103         {104             get;105             set;106         }107         internal  PropertyInfo ReferenceProperty108         {109             get;110             set;111         }112         public static Type TType113         {114             get;115             set;116         }117         118         public  TreeCollection(string keyProperty, string referenceProperty)119         {120             TType = typeof(T);121             KeyProperty = TType.GetProperty(keyProperty);122             ReferenceProperty =TType.GetProperty( referenceProperty);123             T entity = new T();124             TreeNode<T> node = new TreeNode<T>(entity);125             this.Items.Add(node);126         }127         public TreeCollection(IEnumerable<T> rawDatas,string keyProperty,string referenceProperty):this(keyProperty,referenceProperty)128         {129             foreach (var i in rawDatas)130             {131                 Add(i);132             }133         }134         public TreeCollection(IEnumerable<T> rawDatas)135             : this(rawDatas, DefaultKeyProperty, DefaultReferenceProperty)136         { }137         public  TreeCollection() : this(DefaultKeyProperty, DefaultReferenceProperty) 138         { }139         public TreeNode<T> RootNode140         {141             get142             {143                 return this.Items.Where(i => i.Parent == null).FirstOrDefault();144             }145         }146         public TreeNode<T> Add(T entity)147         {148             foreach (var i in this.Items)149             {150                var val =  KeyProperty.GetValue(i.Entity, null);151                 if(val != null && val.Equals(KeyProperty.GetValue(entity,null)))152                 {153                     return i;154                 }155             }156             var parent = FindParentNode(RootNode, entity)??RootNode;157             var node = new TreeNode<T>(entity);158             node.Level = parent.Level + 1;159             var len = parent.ChildNodes.Count();160             if (len >0)161             {162                 var prev = parent.ChildNodes[len - 1];163                 node.NextNode = prev.NextNode;164                 prev.NextNode = node;165                 node.PreviouNode = prev;166             } 167             node.Parent = parent;168             parent.ChildNodes.Add(node);169             this.Items.Add(node);170             return node;171           172         }173         public TreeNode<T> AddAt(T entity, int index)174         {175             if(index<0)176             {177                 throw new ArgumentOutOfRangeException("index");178             }179            180             foreach (var i in this.Items)181             {182                 var val = KeyProperty.GetValue(i.Entity, null);183                 if (val.Equals(KeyProperty.GetValue(entity, null)))184                 {185                     return i;186                 }187             }188             var parent = FindParentNode(RootNode, entity) ?? RootNode;189             var node = new TreeNode<T>(entity);190             node.Parent = parent;191             var bfcount = parent.ChildNodes.Count;192          193             var prevIndex = index - 1;194             var nextIndex = index;195             if (prevIndex > 0 && prevIndex < bfcount)196             {197                 var prev = parent.ChildNodes[prevIndex];198                 if (prev != null)199                 {200                     node.PreviouNode = prev;201                     prev.NextNode = node;202                 }203 204             }205             if (nextIndex > 0 && nextIndex < bfcount)206             {207                 var next = parent.ChildNodes[index];208                 if (next != null)209                 {210                     node.NextNode = next;211                     next.PreviouNode = node;212                 }213             }214             parent.ChildNodes.Insert(index, node);215             this.Items.Add(node);216             return node;217         }218         219         public TreeNode<T> Remove(T entity)220         {221             var val = KeyProperty.GetValue(entity, null);222             var node = FindNodeByKeyProperty(val);223             if (node != null)224             {225                 if (node.PreviouNode != null)226                 {227                     node.PreviouNode.NextNode = node.NextNode;228                 }229                 node.Parent.ChildNodes.Remove(node);230                 node.Parent = null;231                 this.Items.Remove(node);232             }233             return node;234         }235         public void MoveTo(TreeNode<T> node, TreeNode<T> parent,int index)236         {237             if (parent == null)238             {239                 return;240             }241             var entity = node.Entity;242             Remove(entity);243             var val = KeyProperty.GetValue(parent, null);244             ReferenceProperty.SetValue(entity, val,null);245             AddAt(entity, index);246         }247         public TreeNode<T> this[int level, int index]248         {249             get250             {251                return this.Items.Where(i => i.Level == level).Skip(index).First();252             }253         }254         public TreeNode<T> FindNodeByKeyProperty(object keyPropertyValue)255         {256            257             foreach (var i in this.Items)258             {259                 if (KeyProperty.GetValue(i, null).Equals(keyPropertyValue))260                 {261                     return i;262                 }263             }264             return null;265         }266         267         internal TreeNode<T> FindParentNode(TreeNode<T> node,T entity)268         {269 270             var keyValue = KeyProperty.GetValue(node.Entity, null);271             var refValue = ReferenceProperty.GetValue(entity, null);272             if (refValue.Equals(keyValue))273             {274                 return node;275             }276             else277             {278                 TreeNode<T> temp = null;279                 foreach (var i in node.ChildNodes)280                 {281                     temp =  FindParentNode(i, entity);282                     if (temp != null)283                     {284                         return temp;285                     }286                 }287             }288            289             return null;290         }291     }

后台树控件扩展代码

View Code

  1  public static class TreeViewItemConnectingLine  2     {  3         internal static TreeViewItemSingleLineInfo GetSingleConnectingLine(TreeViewItem element)  4         {  5             if (element == null)  6             {  7                 throw new ArgumentNullException("element");  8             }  9             TreeViewItemSingleLineInfo info = element.GetValue(SingleConnectingLineProperty) as TreeViewItemSingleLineInfo; 10             if (info == null) 11             { 12                 info = new TreeViewItemSingleLineInfo(element); 13                 element.SetValue(SingleConnectingLineProperty, info); 14             } 15             return info; 16         } 17         internal static readonly DependencyProperty SingleConnectingLineProperty = 18             DependencyProperty.RegisterAttached( 19             "SingleConnectingLine", 20             typeof(TreeViewItemSingleLineInfo), 21             typeof(TreeViewItemConnectingLine), 22             new PropertyMetadata(null)); 23         public static TreeViewItem GetIsSingleConnectingLineOf(Line element) 24         { 25             if (element == null) 26             { 27                 throw new ArgumentNullException("element"); 28             } 29             return element.GetValue(IsSingleConnectingLineOfProperty) as TreeViewItem; 30         } 31         public static void SetIsSingleConnectingLineOf(Line element, TreeViewItem value) 32         { 33             if (element == null) 34             { 35                 throw new ArgumentNullException("element"); 36             } 37             element.SetValue(IsSingleConnectingLineOfProperty, value); 38         } 39         public static readonly DependencyProperty IsSingleConnectingLineOfProperty = 40             DependencyProperty.RegisterAttached("IsSingleConnectingLineOf", 41             typeof(TreeViewItem), 42             typeof(TreeViewItemConnectingLine), 43             new PropertyMetadata(null, OnIsSingleConnectingLineOfPropertyChanged)); 44         private static void OnIsSingleConnectingLineOfPropertyChanged(DependencyObject d, 45             DependencyPropertyChangedEventArgs e) 46         { 47             Line source = d as Line; 48             TreeViewItem value = e.NewValue as TreeViewItem; 49             if (value != null) 50             { 51                 TreeViewItemSingleLineInfo info = GetSingleConnectingLine(value); 52                 info.ConnectingLine = source; 53             } 54             else 55             { 56                 value = e.OldValue as TreeViewItem; 57                 if (value != null) 58                 { 59                     TreeViewItemSingleLineInfo info = GetSingleConnectingLine(value); 60                     info.ConnectingLine = null; 61                 } 62             } 63         } 64  65         public static TreeViewItem GetIsHeaderOf(FrameworkElement element) 66         { 67             if (element == null) 68             { 69                 throw new ArgumentNullException("element"); 70             } 71             return element.GetValue(IsHeaderOfProperty) as TreeViewItem; 72         } 73         public static void SetIsHeaderOf(FrameworkElement element, TreeViewItem value) 74         { 75             if (element == null) 76             { 77                 throw new ArgumentNullException("element"); 78             } 79             element.SetValue(IsHeaderOfProperty, value); 80         } 81         public static readonly DependencyProperty IsHeaderOfProperty = 82            DependencyProperty.RegisterAttached( 83                "IsHeaderOf", 84                typeof(TreeViewItem), 85                typeof(TreeViewItemConnectingLine), 86                new PropertyMetadata(null, OnIsHeaderOfPropertyChanged)); 87         private static void OnIsHeaderOfPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 88         { 89             FrameworkElement source = d as FrameworkElement; 90             TreeViewItem value = e.NewValue as TreeViewItem; 91  92             if (value != null) 93             { 94                 TreeViewItemSingleLineInfo info = GetSingleConnectingLine(value); 95                 info.Header = source; 96             } 97             else 98             { 99                 value = e.OldValue as TreeViewItem;100                 if (value != null)101                 {102                     TreeViewItemSingleLineInfo info = GetSingleConnectingLine(value);103                     info.Header = null;104                 }105             }106         }107 108     }109     110     public class TreeViewItemSingleLineInfo111     {112         public TreeViewItem Item { get; private set; }113         public Line ConnectingLine { get; set; }114         public FrameworkElement Header { get; set; }115         public TreeViewItemSingleLineInfo(TreeViewItem item)116         {117             Debug.Assert(item != null, "item should not be null!");118             Item = item;119             item.LayoutUpdated += (s, e) => PositionConnectingLines("LayoutUpdated");120             item.Expanded += (s, e) => PositionConnectingLines("Expanded");121             item.Collapsed += (s, e) => PositionConnectingLines("Collapsed");122             item.ItemContainerGenerator.ItemsChanged += (s, e) => PositionConnectingLines("ItemsChanged");123             124         }125 126         private void PositionConnectingLines(string eventName)127         {128             if (Item.GetIsRoot())129             {130                131                 return;132             }133             if (ConnectingLine == null)134             {135                 return;136              137             }138             var parentTreeViewItem = Item.GetParentTreeViewItem();139             if (parentTreeViewItem == null) { return; }140 141             var fromElement = TreeViewItemConnectingLine.GetSingleConnectingLine(parentTreeViewItem).Header;142             if (fromElement == null)143             {144                 ConnectingLine.Visibility = Visibility.Collapsed;145                 return;146             }147            Rect? bound = fromElement.GetBoundsRelativeTo(ConnectingLine);148            ConnectingLine.X1 = bound.Value.X+bound.Value.Width/2;149            ConnectingLine.Y1 = bound.Value.Y+bound.Value.Height/2;150 151            bound = Header.GetBoundsRelativeTo(ConnectingLine);152 153            ConnectingLine.X2 = bound.Value.X + bound.Value.Width / 2;154            ConnectingLine.Y2 = bound.Value.Y + bound.Value.Height / 2;155 156            ConnectingLine.Visibility = Visibility.Visible;157          158         }159     }

转载于:https://www.cnblogs.com/mayamoon/archive/2011/10/06/Custom_Organization_TreeView.html

Siverlight 自定义TreeView 显示带连接线的组织结构树相关推荐

  1. android java 圆角_Android自定义View实现带4圆角或者2圆角的效果

    1 问题 实现任意view经过自定义带4圆角或者2圆角的效果 2 原理 1) 实现view 4圆角 我们只需要把左边的图嵌入到右边里面去,最终显示左边的图就行. 2) 实现view上2圆角 我们只需要 ...

  2. android 两边圆角,Android自定义View实现带4圆角或者2圆角的效果

    1 问题 实现任意view经过自定义带4圆角或者2圆角的效果 2 原理 1) 实现view 4圆角 我们只需要把左边的图嵌入到右边里面去,最终显示左边的图就行. 2) 实现view上2圆角 我们只需要 ...

  3. 一分钟学会自定义右上角显示数字的ImageView

    平时在一些app上会看到一些图标的右上角会显示数字,如微信的头像右上角显示信息数量,淘宝的购物车图标右上角显示商品数量.本人最近也在努力学习自定义控件,下面是本人实现的一个简陋的带数字的ImageVi ...

  4. 基于vue的组织架构树组件_Vue组件基于D3.js布局显示树

    基于vue的组织架构树组件 Vue.D3.tree (Vue.D3.tree) Update documentationVue components to display graphics based ...

  5. HQChart使用教程2- 如何把自定义指标显示在K线图页面

    如何把自定义指标显示在K线图页面 自定义一个指标 通过Option设置指标 自定义一个带参数的指标 让我们用上证指数来回测这个奇葩的BS指标吧 HQChart代码地址 效果图 自定义一个指标 假设我们 ...

  6. Leaflet中使用awesome-markers插件显示带图标的marker

    场景 Vue+Leaflet实现加载OSM显示地图: Vue+Leaflet实现加载OSM显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 在上面的基础上,实现Marker上带图标 ...

  7. Android自定义文件路径箭头,Android自定义ViewGroup实现带箭头的圆角矩形菜单

    本文和大家一起做一个带箭头的圆角矩形菜单,大概长下面这个样子: 要求顶上的箭头要对准菜单锚点,菜单项按压反色,菜单背景色和按压色可配置. 最简单的做法就是让UX给个三角形的图片往上一贴,但是转念一想这 ...

  8. bootstrap bootstraptable 固定列_1个Excel公式按条件自定义格式显示固定电话号码

    点击右上角"关注",每天免费获取干货教程 前面写了很多篇关于数据查询.数据统计.数据分析.公式排错的教程,今天换一个口味,写个关于自定义格式显示数据的教程. 因为工作中很多时候都需 ...

  9. Android 自定义 ListView 显示网络上 JSON 格式歌曲列表

    本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...

  10. WPF学习笔记(7):DataGrid中数字自定义格式显示

    WPF学习笔记(7):DataGrid中数字自定义格式显示 原文:WPF学习笔记(7):DataGrid中数字自定义格式显示 DataGrid中数据显示如下图,数据格式比较杂乱.希望达到以下要求:(1 ...

最新文章

  1. vue饼图统计_做可交互的统计图表,这套图形语法不容错过
  2. jQuery中读取json文件示例代码
  3. 在大数据时代,每家公司都要有大数据部门吗?
  4. fastdfs连接mysql_fastDFS文件上传简单案例
  5. Spring Boot笔记-@PathVariable的使用
  6. mybatis分页插件_MyBatis 分页插件 5.2.0 发布
  7. 使用IIS 7.0 Smooth Streaming 优化视频服务
  8. c语言入门经典+第5版+习题答案,《C语言入门经典(第5版)》—甲虎网一站式图书批发平台...
  9. opencv如何隐藏窗口
  10. 计算机二级考试能不能用键盘,计算机二级 ,你中招了吗?
  11. 没有公网IP?快解析实现内网穿透
  12. 如何进行大数据处理?大数据处理的方法步骤
  13. java如何等待异步结果_你如何等待所有异步调用在Java中完成?
  14. windows 平台使用dul 抽取Linux oracle ASM 磁盘数据文件
  15. C++STL详解(一)string类的使用及其模拟实现
  16. 用switch做了一个简单的计算器可以进行四则运算和模运算
  17. 【证明】线性变换在两个基下的矩阵相似
  18. Matlab中连续信号与离散信号的绘制
  19. 基于云的视频会议五大优点
  20. 使用python读取gif,合并gif,视频转换为gif

热门文章

  1. 常见的三种Content-Type
  2. SqlServer修改sa的密码
  3. 15. 注意string实现的多样性
  4. ipoo3可以用鸿蒙,vivo新机入网!支持44W快充 配置与iQOO Neo3类似
  5. Spring基于XML的IOC细节
  6. java文件编译为class文件需要键入什么命令_Day02:Java语言基础-第一个Java程序以及编译与运行机制...
  7. vb6 由于超出容量限制 不能创建新事务_Executors类创建四种常见线程池
  8. arraylist 线性不安全_Java面试系列(一)--集合类ArrayList
  9. Javascript:获取点击的li标签内部文字
  10. SQL:postgresqll查询某字段各情况数量