如何在Treeview中提供指向节点的链接?

时间:2014-09-30 11:52:31

标签: wpf c#-4.0 wpf-controls wpftoolkit

我想开发一个WPF应用程序,如下面的图像,..在那个应用程序中,我需要连接treeview的两个子节点(通过蓝色线连接的子节点)。

enter image description here

我该怎么做?

1 个答案:

答案 0 :(得分:0)

这就是我的想法。你需要定义你如何找到匹配的方式,我只是用标题值来模拟它。

这是非常粗糙的,可以做一些爱,但我相信它会做你想要的。

enter image description here

<Window x:Class="WpfApplication64.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" WindowStartupLocation="CenterScreen">
<DockPanel>
    <Button Content="AddNode"
            Click="AddNodeClick"
            DockPanel.Dock="Top" />
    <TreeView BorderThickness="1"
              BorderBrush="Black"
              Name="treeView"
              Width="300">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}"
                   BasedOn="{StaticResource {x:Type TreeViewItem}}">
                <Setter Property="IsExpanded"
                        Value="True" />
            </Style>
        </TreeView.ItemContainerStyle>
    </TreeView>
</DockPanel>

    namespace WpfApplication64
{
    class TreeViewLinksAdorner : Adorner
    {
        public TreeViewLinksAdorner(TreeView adornedElement) :
            base(adornedElement) 
        {
            SnapsToDevicePixels = true;

            adornedElement.AddHandler(TreeViewItem.CollapsedEvent, new RoutedEventHandler(OnIsExpandedChanged));
            adornedElement.AddHandler(TreeViewItem.ExpandedEvent, new RoutedEventHandler(OnIsExpandedChanged));
        }

        void OnIsExpandedChanged(object sender, RoutedEventArgs e)
        {
            InvalidateVisual();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            Brush[] colours = new Brush[] { Brushes.Red, Brushes.Green, Brushes.Blue };
            TreeView treeView = (TreeView)AdornedElement;
            var treeViewItems = GetVisibleTreeViewItems(treeView);
            var processed = new HashSet<string>();
            double offset = 6;
            int brushIndex = 0;
            double width = treeView.ActualWidth - SystemParameters.ScrollWidth;

            foreach (var tvi1 in treeViewItems)
            {
                if(processed.Contains(tvi1.Header.ToString()))
                {
                    continue;
                }

                bool found = false;
                foreach (var tvi2 in treeViewItems)
                {
                    if (tvi1 == tvi2)
                    {
                        continue;
                    }
                    else if(tvi1.Header.ToString() == tvi2.Header.ToString())
                    {
                        Pen pen = new Pen(colours[brushIndex], 1) { DashStyle = DashStyles.Dash };
                        Point a = LocalPosToAncestorPos((ContentPresenter)tvi1.Template.FindName("PART_Header", tvi1), treeView);
                        Point d = LocalPosToAncestorPos((ContentPresenter)tvi2.Template.FindName("PART_Header", tvi2), treeView);

                        Point b = new Point(width - offset, a.Y);
                        Point c = new Point(width - offset, d.Y);

                        drawingContext.DrawLine(pen, a, b);
                        drawingContext.DrawLine(pen, b, c);
                        drawingContext.DrawLine(pen, c, d);

                        found = true;
                    }
                }

                if(found)
                {
                    brushIndex = brushIndex < colours.Length - 1 ? brushIndex + 1 : 0;
                    offset += 6;
                }

                processed.Add(tvi1.Header.ToString());
            }
        }

        Point LocalPosToAncestorPos(FrameworkElement child, FrameworkElement ancestor)
        {
            Point localPos = new Point(child.ActualWidth, child.ActualHeight * 0.5);
            return child.TransformToAncestor(ancestor).Transform(localPos);
        }

        List<TreeViewItem> GetVisibleTreeViewItems(FrameworkElement parent)
        {
            var treeViewItems = new List<TreeViewItem>();

            for (int i = 0, count = VisualTreeHelper.GetChildrenCount(parent); i < count; i++)
            {
                FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;

                var treeViewItem = child as TreeViewItem;
                if (treeViewItem != null)
                {
                    treeViewItems.Add(treeViewItem);
                    if (treeViewItem.IsExpanded)
                    {
                        foreach (var childTreeViewItem in GetVisibleTreeViewItems(child))
                        {
                            treeViewItems.Add(childTreeViewItem);
                        }
                    }
                }
                else
                {
                    foreach (var childTreeViewItem in GetVisibleTreeViewItems(child))
                    {
                        treeViewItems.Add(childTreeViewItem);
                    }
                }
            }

            return treeViewItems;
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            Loaded += OnLoaded;
            InitializeComponent();

            AddNode();
            AddNode();
        }

        void OnLoaded(object sender, RoutedEventArgs e)
        {
            AdornerLayer.GetAdornerLayer(treeView).Add(new TreeViewLinksAdorner(treeView));
        }

        void AddNodeClick(object sender, RoutedEventArgs e)
        {
            AddNode();
        }

        void AddNode()
        {
            TreeViewItem parent = new TreeViewItem() { Header = "item" + treeView.Items.Count };
            parent.Items.Add(new TreeViewItem() { Header = "subItem" + subCount++ });
            parent.Items.Add(new TreeViewItem() { Header = "subItem" + subCount++ });
            parent.Items.Add(new TreeViewItem() { Header = "$" });
            parent.Items.Add(new TreeViewItem() { Header = "subItem" + subCount++ });
            parent.Items.Add(new TreeViewItem() { Header = "$$" });
            parent.Items.Add(new TreeViewItem() { Header = "$$$" });
            parent.Items.Add(new TreeViewItem() { Header = "subItem" + subCount++ });
            parent.Items.Add(new TreeViewItem() { Header = "$$$$" });
            treeView.Items.Add(parent);
        }

        int subCount;
    }
}