示例代碼:TreeViewEx.zip 原文地址:http://www./Tips/673071/WPF-TreeView-with-WinForms-Style-Fomat IntroductionWPF default Now, I myself designed a Source CodeAll you need is an XAML file and a code behind. First, you need draw Toggle Button: From Triangle button to Plus-Minus button: draw a rectangle with dark border, then draw two lines, one vertical line and one horizontal line. When <!-- Toggle Button --> <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> <Setter Property="Focusable" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Grid Width="15" Height="13" SnapsToDevicePixels="True"> <!-- Rectangle 9x9 pixels --> <Rectangle Width="9" Height="9" Stroke="#919191" SnapsToDevicePixels="true"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,2" StartPoint="0.5,0"> <GradientStop Color="White" Offset="0"/> <GradientStop Color="Silver" Offset="0.5"/> <GradientStop Color="LightGray" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <!-- Vertical line inside rectangle --> <Rectangle x:Name="ExpandPath" Width="1" Height="5" Stroke="Black" SnapsToDevicePixels="true"/> <!-- Horizontal line inside rectangle --> <Rectangle Width="5" Height="1" Stroke="Black" SnapsToDevicePixels="true"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter Property="Visibility" TargetName="ExpandPath" Value="Collapsed"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> In the above code, you can see a trigger, it will make the vertical line inside toggle button hide if item is expanded, or show if its children collapsed. Then, you need to draw vertical and horizontal connecting lines between nodes: You need to redesign <!-- Horizontal line --> <Rectangle x:Name="HorLn" Margin="9,1,0,0" Height="1" Stroke="#DCDCDC" SnapsToDevicePixels="True"/> <!-- Vertical line --> <Rectangle x:Name="VerLn" Width="1" Stroke="#DCDCDC" Margin="0,0,1,0" Grid.RowSpan="2" SnapsToDevicePixels="true" Fill="White"/> to your <!-- TreeViewItem --> <Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TreeViewItem}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition MinWidth="19" Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <!-- Connecting Lines --> <!-- Horizontal line --> <Rectangle x:Name="HorLn" Margin="9,1,0,0" Height="1" Stroke="#DCDCDC" SnapsToDevicePixels="True"/> <!-- Vertical line --> <Rectangle x:Name="VerLn" Width="1" Stroke="#DCDCDC" Margin="0,0,1,0" Grid.RowSpan="2" SnapsToDevicePixels="true" Fill="White"/> <!-- Insert Toggle Button --> <ToggleButton Margin="-1,0,0,0" x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/> <Border Name="Bd" Grid.Column="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" MinWidth="20"/> </Border> <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> Then, you need put the class using System; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace TreeViewEx { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } class TreeViewLineConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { TreeViewItem item = (TreeViewItem)value; ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item); return ic.ItemContainerGenerator.IndexFromContainer(item) == ic.Items.Count - 1; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return false; } } } Insert your namespace to your XAML, i.e.: <Window x:Class="TreeViewEx.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TreeViewEx"/> Add this line to <local:TreeViewLineConverter x:Key="LineConverter"/> Add trigger to <!-- This trigger changes the connecting lines if the item is the last in the list --> <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LineConverter}}" Value="true"> <Setter TargetName="VerLn" Property="Height" Value="9"/> <Setter TargetName="VerLn" Property="VerticalAlignment" Value="Top"/> </DataTrigger> The ToDoIn WinForms <!-- Connecting Lines --> <Rectangle x:Name="HorLn" Margin="9,1,0,0" Height="1" Stroke="#DCDCDC" SnapsToDevicePixels="True"/> <Rectangle x:Name="VerLn" Width="1" Stroke="#DCDCDC" Margin="0,0,1,0" Grid.RowSpan="2" SnapsToDevicePixels="true" Fill="White"/> To: <!-- Connecting Lines --> <Rectangle x:Name="HorLn" Margin="9,1,0,0" Height="1" Stroke="Blue" StrokeDashCap="Square" StrokeDashArray="0,2" StrokeDashOffset="1" SnapsToDevicePixels="True"/> <Rectangle x:Name="VerLn" Width="1" Stroke="Blue" StrokeDashCap="Square" StrokeDashArray="0,2" Margin="0,0,1,0" Grid.RowSpan="2" SnapsToDevicePixels="true" Fill="White"/> But it is not pretty, as you see. As I'm a newbie in WPF, I don't know to style these lines perfectly. ReferenceThis is the code I referenced before I wrote my own:
|
|
來自: 牛人的尾巴 > 《treeview控件》