WPF - TreeView 仿VS2013解决方案资源管理器中的树状结构

效果图

先上效果图,若是你想要的效果,可以继续看下面的代码,不想浪费大家的时间。

样式定义

此处定义TreeView的样式,参考自MSDN,稍作修改。

注意:在TreeViewItem控件模板定义中绑定一个数据(Level)以及一个值转换器(LevelToMarginConverter),具体定义见下部分。

<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Border Width="12" Height="14">
                    <Path x:Name="ExpandPath" HorizontalAlignment="Right" VerticalAlignment="Center"
                            Fill="Transparent" Stroke="#FFE6E6E6" Data="M 2 2 L 7 7 L 2 12 Z"/>
                </Border>
                <ControlTemplate.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsChecked" Value="False"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                    </MultiTrigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="Data" TargetName="ExpandPath" Value="M 1 10 L 7 3 L 7 10 Z"/>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="#FFE6E6E6"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsChecked" Value="True"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                    </MultiTrigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="TreeViewItemFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Border>
                    <Rectangle Margin="0,0,0,0" StrokeThickness="5" Stroke="Black" StrokeDashArray="1 2" Opacity="0" Fill="Black"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ModernTreeViewItem" TargetType="{x:Type TreeViewItem}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="Padding" Value="1,0,0,0"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                        <Grid Margin="{Binding Level, Converter={StaticResource LevelToMarginConverter}}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="auto"/>
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" ClickMode="Press" HorizontalAlignment="Left"
                                            IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
                            <ContentPresenter Grid.Column="1" Margin="8,0,0,0" x:Name="PART_Header" ContentSource="Header"
                                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                        </Grid>
                    </Border>
                    <ItemsPresenter x:Name="ItemsHost" Grid.Row="1"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="false">
                        <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false"/>
                            <Condition Property="Width" Value="Auto"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false"/>
                            <Condition Property="Height" Value="Auto"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
                    </MultiTrigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="IsSelectionActive" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

值转换器定义

此转换器主要用于根据子节点的级数计算每行内容的缩进,根节点级数为1,根节点的子节点级数为2,依次类推。

class LevelToMarginConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var level = (int)value;
        return new System.Windows.Thickness(8 * level + 10 * (level - 1), 0, 0, 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

数据定义

此处定义的TreeView空间绑定的数据。

注意:在TreeNode类中定义了Level属性,用于指示当前节点的级数。

public class TreeViewData
{
    private static TreeViewData _Data = null;

    public static TreeViewData Data
    {
        get
        {
            if(_Data == null)
            {
                _Data = new TreeViewData();

                var rn1 = new TreeNode() { Label = "Root A", Level = 1 };
                rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 1", Level = 2 });
                rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 2", Level = 2 });
                rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 3", Level = 2 });
                rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 4", Level = 2 });
                rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 5", Level = 2 });

                var rn2 = new TreeNode() { Label = "Root B", Level = 1 };
                rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 1", Level = 2 });

                var rn21 = new TreeNode() { Label = "Root B - Child 2", Level = 2 };
                rn21.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 2 - Child 1", Level = 3 });
                rn21.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 2 - Child 2", Level = 3 });
                rn2.ChildNodes.Add(rn21);
                rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 3", Level = 2 });
                rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 4", Level = 2 });
                rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 5", Level = 2 });

                var rn3 = new TreeNode() { Label = "Root C", Level = 1 };
                rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 1", Level = 2 });
                rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 2", Level = 2 });
                rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 3", Level = 2 });
                rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 4", Level = 2 });
                rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 5", Level = 2 });

                _Data.RootNodes.Add(rn1);
                _Data.RootNodes.Add(rn2);
                _Data.RootNodes.Add(rn3);
            }
            return _Data;
        }
    }

    private System.Collections.ObjectModel.ObservableCollection<TreeNode> _RootNodes = null;

    public IList<TreeNode> RootNodes { get { return _RootNodes ?? (_RootNodes = new System.Collections.ObjectModel.ObservableCollection<TreeNode>()); } }

    public class TreeNode
    {
        public string Label { get; set; }

        public int Level { get; set; }

        private System.Collections.ObjectModel.ObservableCollection<TreeNode> _ChildNodes = null;

        public IList<TreeNode> ChildNodes { get { return _ChildNodes ?? (_ChildNodes = new System.Collections.ObjectModel.ObservableCollection<TreeNode>()); } }
    }
}

应用样式

<TreeView ItemsSource="{Binding Source={x:Static data:TreeViewData.Data}, Path=RootNodes}"
          HorizontalContentAlignment="Stretch" Background="#FF252526" Width="300" ItemContainerStyle="{StaticResource ModernTreeViewItem}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type data:TreeViewData+TreeNode}" ItemsSource="{Binding ChildNodes}">
            <Grid Height="32">
                <TextBlock Text="{Binding Label}" VerticalAlignment="Center" Foreground="#FFE6E6E6" FontSize="13"/>
            </Grid>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
时间: 2024-12-10 04:54:09

WPF - TreeView 仿VS2013解决方案资源管理器中的树状结构的相关文章

mvc 分部视图(Partial)显示登陆前后变化以及Shared文件夹在解决方案资源管理器中没有显示的问题

刚开始我的解决方案资源管理器中没有显示Shared文件夹,但Shared文件夹在项目中是实际存在的,我搜了下好像没有类似的解答(可能是我搜索的关键词不够准确).后来自己看了下vs2012. 其实解决方法很简单: 首先,视图->解决方案资源管理器.在解决方案资源管理器中点击下图中的红色方框中那个"显示所有文件". 然后会出现类似图片中的文件,找到自己要的,鼠标右击一下,点击下图中红色方框中的“包括在项目中”即可. mvc分部视图显示登陆前后的变化 前后效果是这样的 登录前:: 登陆

VS 解决方案资源管理器中限定为此范围的显示与取消

VS 的解决方案资源管理器,为了方便开发人员,精简解决方案资源管理器的显示,提供了 "限定为此范围"的显示: 要想恢复整个解决方案的显示,点击解决方案资源管理上部的主页即可.

签入在服务器上之后,别人获取了,在解决方案资源管理器中找不到。

这个问题具体原因我也不太清楚,但是我找到了一个解决方案.直接在解决方案上右键,添加,添加现有项.把在解决方案资源管理器上看不见的选中,添加就好了.

mysql中递归树状结构&lt;转&gt;

在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. 在MySQL中如果是有限的层次,比如我们事先如果可以确定这个树的最大深度是4, 那么所有节点为根的树的深度均不会超过4,则我们可以直接通过left join 来实现. 但很多时候我们无法控制树的深度.这时就需要在MySQL中用存储过程来实现或在你的程序中来实现这个递归.本文讨论一下几种实现的方法.

vs2010 怎样设置文本编辑窗口和解决方案资源管理器同步?

即切换左边的文本编辑窗口,解决方案资源管理器如何定位到相应的文件项上?答案: 工具--选项--项目和解决方案--常规--在解决方案资源管理器中跟踪活动项(前打勾)确定 应该就可以了. vs2010 怎样设置文本编辑窗口和解决方案资源管理器同步?

vs2005的解决方案资源管理器本在左边,现跑到右边去了,怎样才能将其搬到左边

工具->导入和导出设置->重置所有设置->否,仅重置..,从而改写我的当前设置->下一步选择VisualC++默认设置.完成.更改字体和颜色:工具->选项->环境->字体和颜色,然后按照个人喜好设置字体大小和颜色.增加"生成","运行时不调试","运行时调试":工具->自定义->工具栏,在"生成"前面打勾工具->自定义->命令->工具栏,在后面的下拉列表中

删除资源管理器中,设备和驱动器与左侧边栏中存在的WPS网盘等图标

存在的问题:资源管理器中,设备和驱动器与左侧边栏中存在的百度网盘和WPS网盘等图标,看着比较碍眼,所以想设置为不显示,可是软件本身不提供右键不显示或删除的功能 解决方案: 删除设备和驱动器中不想要的图标 win + R > 输入 regedit 进入注册表 进入以下路径中:计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace,就可以看到非系统的几个图标项 对于想要

Windows 7 在资源管理器中显示软件快捷方式

该方法是利用资源管理器中储存网络位置的文件夹实现的, 不需要修改注册表. 效果如图: 操作方法: 在资源管理器中打开路径 "%appdata%\Microsoft\Windows\Network Shortcuts" 你可以往里面扔 快捷方式,可执行程序,甚至是文件夹.

[Win7]IE中访问FTP网址不能在资源管理器中打开

问题症状:在计算机或者IE中访问FTP网址,不能在资源管理器中打开.始终只能用IE浏览.网上在IE-视图-在资源管理器中浏览FTP等方法无效. 操作系统:Win7 软件版本:IE 11 处理方法: 保存下面的文件为reg注册表文件并导入注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\ftp] @="URL:File Transfer Protocol" "AppUserModelID"=&quo