有粉丝说想看TreeView,今天就来看看它喽。
定义了ViewModel,重写ItemTemplate。
Scroll样式 还是之前 的文章中写的那个:
参见:
先来看一下今天的效果吧:
老规矩,废话不多,直接看代码:
新建一个窗口,全部xaml代码如下:
<Window x:Class="WxDemo.TreeViewDemo"
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:WxDemo"
x:Name="window"
mc:Ignorable="d"
Title="TreeViewDemo" Height="450" Width="800">
<Window.Resources>
<local:TreeItemMarginConverter x:Key="TreeViewItemMarginConverter"/>
<Style x:Key="TreeViewStyle1" TargetType="{x:Type TreeView}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ScrollViewer x:Name="_tv_scrollviewer_" Background="{TemplateBinding Background}"
CanContentScroll="false" Focusable="false"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
<ItemsPresenter/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
<Setter Property="CanContentScroll" TargetName="_tv_scrollviewer_" Value="true"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ToggleStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="16"/>
<Setter Property="Height" Value="16"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border>
<Image x:Name="toggleImg" Source="/images/arrow16.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform Angle="-90"/>
</Image.RenderTransform>
</Image>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="RenderTransform" TargetName="toggleImg">
<Setter.Value>
<RotateTransform Angle="0"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TreeViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="10,0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="23" />
<RowDefinition />
</Grid.RowDefinitions>
<Border x:Name="Bd" CornerRadius="3" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<DockPanel LastChildFill="True" Margin="{Binding Converter={StaticResource TreeViewItemMarginConverter}, RelativeSource={RelativeSource TemplatedParent}}">
<ToggleButton x:Name="Expander" ClickMode="Press" DockPanel.Dock="Left"
IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ToggleStyle}" />
<ContentPresenter VerticalAlignment="Center" x:Name="PART_Header" ContentSource="Header"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</DockPanel>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.Row="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="Bd">
<Setter Property="Background" TargetName="Bd" Value="lightGray"/>
</Trigger>
<Trigger Property="IsExpanded" Value="False">
<Setter Property="Visibility" Value="Collapsed" TargetName="ItemsHost"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Visibility" TargetName="Expander" Value="Hidden" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="LightBlue" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TreeView Margin="5" Width="300" ItemsSource="{Binding Items,ElementName=window}" Style="{DynamicResource TreeViewStyle1}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding DisplayText}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
窗体后台代码:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace WxDemo
{
public partial class TreeViewDemo : Window, INotifyPropertyChanged
{
private ObservableCollection<ItemViewModel> _items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged(nameof(Items));
}
}
public TreeViewDemo()
{
InitializeComponent();
Items = new ObservableCollection<ItemViewModel>()
{
new ItemViewModel
{
DisplayText="中国人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="马云"},
new ItemViewModel{DisplayText="马化腾"},
new ItemViewModel{
DisplayText="WPF UI作者",
Children=new ObservableCollection<ItemViewModel>(){
new ItemViewModel{ DisplayText="身价:100亿"},
new ItemViewModel{ DisplayText="老婆数:100个"},
}
},
}
},
new ItemViewModel
{
DisplayText="歪果人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="乔布斯"},
new ItemViewModel{DisplayText="巴菲特"},
}
},
new ItemViewModel
{
DisplayText="中国人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="马云"},
new ItemViewModel{DisplayText="马化腾"},
new ItemViewModel{DisplayText="WPF UI作者"},
}
},
new ItemViewModel
{
DisplayText="歪果人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="乔布斯"},
new ItemViewModel{DisplayText="巴菲特"},
}
},
new ItemViewModel
{
DisplayText="中国人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="马云"},
new ItemViewModel{DisplayText="马化腾"},
new ItemViewModel{DisplayText="WPF UI作者"},
}
},
new ItemViewModel
{
DisplayText="歪果人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="乔布斯"},
new ItemViewModel{DisplayText="巴菲特"},
}
},
new ItemViewModel
{
DisplayText="中国人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="马云"},
new ItemViewModel{DisplayText="马化腾"},
new ItemViewModel{DisplayText="WPF UI作者"},
}
},
new ItemViewModel
{
DisplayText="歪果人",
Children=new ObservableCollection<ItemViewModel>
{
new ItemViewModel{DisplayText="乔布斯"},
new ItemViewModel{DisplayText="巴菲特"},
}
},
};
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public string DisplayText { get; set; }
public ObservableCollection<ItemViewModel> Children { get; set; } = new ObservableCollection<ItemViewModel>();
}
}
主窗体中使用到了一个转换器:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace WxDemo
{
public class TreeItemMarginConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var left = 0.0;
UIElement element = value as TreeViewItem;
while (element != null && element.GetType() != typeof(TreeView))
{
element = (UIElement)VisualTreeHelper.GetParent(element);
if (element is TreeViewItem)
left += 18.0;
}
return new Thickness(left, 0, 0, 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
TreeView左侧的小箭头是在Iconfont网站下载的,可以自行下载:
下载时选择宽度16,黑色就行了。
控件色彩搭配不是很好,你可以自行修改哦,LightBlue和Gray的颜色都在xaml文件里。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容