zoukankan      html  css  js  c++  java
  • WPF 自定义TreeView控件样式,仿QQ联系人列表

    一、前言

    TreeView控件在项目中使用比较频繁,普通的TreeView并不能满足我们的需求。因此我们需要滴对TreeView进行改造。下面的内容将介绍仿QQ联系人TreeView样式及TreeView数据绑定方法。

    二、TreeView仿QQ联系人列表

    准确的说不是仿QQ联系人列表,这个TreeView样式作为组织架构来使用更好。废话不多说,先看效果:

     2.1、基本思路

    像这种联系人列表一般涉及到多层级数据,而且有很多数据是需要动态更新的,如果通过手动一条条增加数据反而更复杂,而且不方便。因此为了绑定数据方便我们使用分层模板HierarchicalDataTemplate。

    分层模板中存在两种样式,一种是分组样式,一种是人员样式。不管是分组还是人员绑定的都是对象,这样我们在对象中添加一个属性来辨别是否为分组-IsGrouping。

    默认的TreeView控件四周会有边距,因此需要设置下TreeView的样式。另外鼠标经过和鼠标选中的背景色需要变化,因此还需要设置TreeViewItem的样式。

    根据思路,我们需要设置三个样式,TreeView样式,TreeViewItem样式,HierarchicalDataTemplate分层模板样式。另外为了自动计算下一级的边距,我们需要添加一个转换器IndentConverter。还需要一个转换器需要将布尔类型的IsGrouping转换为Visibility,还需要一个转换器来对Visibility取反。

    这样三个样式,三个转换器。就可以实现我们上面的效果,另外还可以进行动态数据绑定。

    2.2、样式代码

    HierarchicalDataTemplate分层模板样式代码

     <HierarchicalDataTemplate x:Key="ItemNode" ItemsSource="{Binding Children,Mode=TwoWay}">
                <Grid  Background="Transparent">
                    <Grid.Resources>
                        <convert:BoolToVisible x:Key="boolToVisible"/>
                        <convert:VisibleToReverse x:Key="visibleToReverse"/>
                    </Grid.Resources>
                    <Grid MinHeight="30" x:Name="userinfo" Background="Transparent" Margin="-5 0 0 0" Visibility="{Binding Visibility,ElementName=groupinginfo,Converter={StaticResource visibleToReverse}}">
                        <Grid Height="50" x:Name="grid">
                            <Border Background="#62acf9" Width="40" Height="40" CornerRadius="4" HorizontalAlignment="Left" Margin="0 0 0 0">
                                <TextBlock Text="{Binding SurName}" FontSize="23" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            </Border>
                            <TextBlock Text="{Binding Name}" Margin="50 7 0 0" FontSize="13"/>
                            <TextBlock Text="{Binding Info}" Foreground="#808080" Margin="50 30 0 0"/>
                            <TextBlock Text="{Binding Count,StringFormat={}{0}人}" Foreground="#808080" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0 0 5 0"/>
                        </Grid>
                    </Grid>
                    <StackPanel MinHeight="25" x:Name="groupinginfo" Orientation="Horizontal" Background="Transparent" HorizontalAlignment="Left" Visibility="{Binding IsGrouping,Converter={StaticResource boolToVisible}}">
    
                        <TextBlock Text="{Binding DisplayName}" Margin="3 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                    </StackPanel>
                </Grid>
            </HierarchicalDataTemplate>

    TreeViewItem样式代码

     <Style  x:Key="DefaultTreeViewItem" TargetType="{x:Type TreeViewItem}">
                <Setter Property="MinHeight" Value="25" />
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="SnapsToDevicePixels" Value="True" />
    
                <Setter Property="Margin" Value="0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TreeViewItem}">
                            <ControlTemplate.Resources>
                                <convert:IndentConverter  x:Key="indentConverter"/>
                            </ControlTemplate.Resources>
                            <Grid Background="Transparent">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <Border Name="itemBackground" Background="{TemplateBinding Background}"  
                                    BorderBrush="{TemplateBinding BorderBrush}"  
                                    BorderThickness="{TemplateBinding BorderThickness}"  
                                    Padding="{TemplateBinding Padding}">
                                    <Grid Background="Transparent">
                                        <Grid x:Name="ItemRoot" Margin="{Binding Converter={StaticResource indentConverter},RelativeSource={RelativeSource TemplatedParent}}" Background="Transparent">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="16" />
                                                <ColumnDefinition Width="*"/>
                                            </Grid.ColumnDefinitions>
    
                                            <ToggleButton x:Name="Expander" HorizontalAlignment="Left" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}">
                                                <ToggleButton.Style>
                                                    <Style TargetType="{x:Type ToggleButton}">
                                                        <Setter Property="Focusable" Value="False"/>
                                                        <Setter Property="Width" Value="16"/>
                                                        <Setter Property="Height" Value="16"/>
                                                        <Setter Property="Template">
                                                            <Setter.Value>
                                                                <ControlTemplate TargetType="{x:Type ToggleButton}">
                                                                    <Border Background="Transparent" Height="16" Padding="5" Width="16">
                                                                        <Path x:Name="ExpandPath" Data="M0,0 L0,6 L6,0 z" Fill="#66645e" Stroke="#66645e">
                                                                            <Path.RenderTransform>
                                                                                <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                                                                            </Path.RenderTransform>
                                                                        </Path>
                                                                    </Border>
                                                                    <ControlTemplate.Triggers>
                                                                        <Trigger Property="IsChecked" Value="True">
                                                                            <Setter Property="RenderTransform" TargetName="ExpandPath">
                                                                                <Setter.Value>
                                                                                    <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                                                                                </Setter.Value>
                                                                            </Setter>
                                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#66645e"/>
                                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#66645e"/>
                                                                        </Trigger>
                                                                        <Trigger Property="IsMouseOver" Value="True">
                                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#66645e"/>
                                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#66645e"/>
                                                                        </Trigger>
                                                                        <MultiTrigger>
                                                                            <MultiTrigger.Conditions>
                                                                                <Condition Property="IsMouseOver" Value="True"/>
                                                                                <Condition Property="IsChecked" Value="True"/>
                                                                            </MultiTrigger.Conditions>
                                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#66645e"/>
                                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#66645e"/>
                                                                        </MultiTrigger>
                                                                    </ControlTemplate.Triggers>
                                                                </ControlTemplate>
                                                            </Setter.Value>
                                                        </Setter>
                                                    </Style>
                                                </ToggleButton.Style>
                                            </ToggleButton>
                                            <ContentPresenter Grid.Column="1" x:Name="PART_Header" ContentSource="Header"  
                                                     HorizontalAlignment="Stretch" >
    
                                            </ContentPresenter>
                                        </Grid>
                                    </Grid>
    
                                </Border>
                                <ItemsPresenter x:Name="ItemsHost" Grid.Row="1"/>
                            </Grid>
    
                            <ControlTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsGrouping}" Value="false">
                                    <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
                                </DataTrigger>
                                <Trigger Property="HasItems" Value="False">
                                    <Setter Property="Visibility" TargetName="Expander" Value="Collapsed"/>
                                </Trigger>
                                <Trigger Property="IsExpanded" Value="False">
                                    <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
                                </Trigger>
    
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Background" TargetName="itemBackground" Value="#FAE388"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsFocused" Value="False"/>
                                        <Condition SourceName="itemBackground" Property="IsMouseOver" Value="true"/>
                                    </MultiTrigger.Conditions>
                                    <Setter Property="Background" Value=" #fceeb9" TargetName="itemBackground"/>
                                </MultiTrigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    TreeView样式代码

      <Style x:Key="DefaultTreeView" TargetType="{x:Type TreeView}">
                <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
                <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
                <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
                <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
                <Setter Property="ItemContainerStyle" Value="{StaticResource DefaultTreeViewItem}"></Setter>
                <Setter Property="Padding" Value="0"/>
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel IsItemsHost="True" Margin="0"/>
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    2.3、转换器代码

     public class IndentConverter : IValueConverter
        {
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                double colunwidth = 10;
                double left = 0.0;
    
    
                UIElement element = value as TreeViewItem;
                while (element.GetType() != typeof(TreeView))
                {
                    element = (UIElement)VisualTreeHelper.GetParent(element);
                    if (element.GetType() == typeof(TreeViewItem))
                        left += colunwidth;
                }
                return new Thickness(left, 0, 0, 0);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    
        }
    
        public class BoolToVisible : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if ((bool)value)
                    return Visibility.Visible;
                else
                    return Visibility.Collapsed;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
        public class VisibleToReverse : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if ((Visibility)value == Visibility.Visible)
                    return Visibility.Collapsed;
                else
                    return Visibility.Visible;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    2.4、引用示例

      <TreeView x:Name="TreeViewOrg" BorderThickness="1" BorderBrush="#BBB" Background="Transparent" Width="280" Height="500" Margin="10" ItemTemplate="{StaticResource ItemNode}" Style="{StaticResource DefaultTreeView}">
                </TreeView>

    2.5、初始化数据源及绑定对象

    public MainWindow()
            {
                InitializeComponent();
                OrgList = new ObservableCollection<OrgModel>()
                {
                    new OrgModel()
                    {
                        IsGrouping=true,
                        DisplayName="单位名称(3/7)",
                        Children=new ObservableCollection<OrgModel>()
                        {
                            new OrgModel(){
                                IsGrouping=true,
                                DisplayName="未分组联系人(2/4)",
                                Children=new ObservableCollection<OrgModel>()
                                {
                                    new OrgModel(){
                                        IsGrouping=false,
                                        SurName="",
                                        Name="刘棒",
                                        Info="我要走向天空!",
                                        Count=3
                                    }
                                }
                            }
                        },
                    }
    
                };
                TreeViewOrg.ItemsSource = OrgList;
            }
    
            public ObservableCollection<OrgModel> OrgList { get; set; }
    
            public class OrgModel
            {
                public bool IsGrouping { get; set; }
                public ObservableCollection<OrgModel> Children { get; set; }
                public string DisplayName { get; set; }
                public string SurName { get; set; }
                public string Name { get; set; }
                public string Info { get; set; }
                public int Count { get; set; }
            }

    所有代码已经上传到github:https://github.com/cmfGit/WpfDemo.git

  • 相关阅读:
    javascript中万恶的function
    Windows7下如何安装部署秋色园CYQBlog源码V1.0网站
    Extjs2.2:Panel里面嵌入Excel表格
    Extjs做界面很酷;感谢博客园给我一个展示的机会;借此向大家展示一下EXTJS的魅力
    16Aspx.com改进版Extjs简单版酒店管理系统提供下载!
    Ext2.2+ASP.NET开发框架已完成欢迎大家下载!
    Extj+Asp.net开发框架V1.1树的操作
    Ext2.2程序开发实战(1)登录界面
    扩展欧几里得定理
    C语言 统计整数二进制表示中1的个数
  • 原文地址:https://www.cnblogs.com/xiaomingg/p/8765802.html
Copyright © 2011-2022 走看看