文章目录
- 背景
- 效果预览
- 方案设计
- 分析
- 基本布局
- 添加控件自定义属性
- 添加属性值监听
- 获取点数据
- 全部代码
- HorizontalLineContent.xaml
- HorizontalLineContent.xaml.cs
- DirectionAlignment.cs
- ContentDirectionAlignment.cs
- 使用方法
背景
因为项目开发需要,要在WPF上绘制TCP的交互过程图,所以现在需要一个箭头控件,并且在箭头中间还可以加入文字,所以开发了这个HorizontalLineContent
控件,后续可能还要开发垂直版本。😁
效果预览
方案设计
一开始设计的实现逻辑其实是有两种的:
-
Polygon x 1 + Label x 1
然后通过设置层级Index,让文本控件覆盖在图形上,但是有个致命的缺点,就是文本控件不能设置背景颜色为透明色,不然图形就会和文字重叠,所以没有采用该方案。 -
Polygon x 2 + Label x 1
通过计算Label的渲染宽度,然后计算两边图形的点数据,然后绘制图形,虽然该方案比上一个要繁琐一点,但是效果会好很多,后面也可以方便扩展其它的属性,比如:整体旋转、单独图形旋转、单独文字旋转等。
我这里目前只考虑了如下几个要素:
- 直线大小
- 控件颜色,这里没有做Text和箭头颜色的分开
- 文本位置
- 箭头方向
- 箭头宽度和高度
核心的几点逻辑是:
- 我分为了两个Polygon去绘制图形,一个在左边,一个在右边,通过设置箭头方向然后确定哪一个Polygon去绘制箭头,另一个去绘制直线。
- 文本控件在中间水平居中,通过监听自定义控件属性Text的变化,然后重新计算文本控件的宽度,然后绘制控件的点数据。
- 我这里将控件的Foreground属性绑定在了Polygon的Fill属性上,实现图形跟文字一起变色,如果需要单独控制文本和图形的颜色,可以拆开处理。
分析
基本布局
首先我们肯定是需要一个Label控件对文本内容进行显示,其次是需要一个能调整上中下位置的Grid,还需要两个Polygon去绘制图形。
所以基本样式就有了
<Grid><Grid.RowDefinitions><RowDefinition Height="Auto"></RowDefinition><RowDefinition Height="*"></RowDefinition><RowDefinition Height="Auto"></RowDefinition></Grid.RowDefinitions><Polygon Grid.Row="1" x:Name="pol_left" VerticalAlignment="Center" Fill="Black" Panel.ZIndex="1"><Polygon.Points><Point X="0" Y="0"></Point><Point X="35" Y="0"></Point><Point X="35" Y="4"></Point><Point X="0" Y="4"></Point></Polygon.Points></Polygon><Polygon Grid.Row="1" x:Name="pol_right" VerticalAlignment="Center" Fill="Black" Panel.ZIndex="1"><Polygon.Points><Point X="65" Y="0"></Point><Point X="100" Y="0"></Point><Point X="100" Y="4"></Point><Point X="65" Y="4"></Point></Polygon.Points></Polygon><Label Grid.Row="1" x:Name="txt_text" FontFamily="Consolas" Padding="5 0 5 0" VerticalAlignment="Center" HorizontalAlignment="Center" Panel.ZIndex="2"></Label>
</Grid>
在设计器中的效果如下图:
添加控件自定义属性
// 内容
public new object Content
{get { return (string)GetValue(ContentProperty); }set { SetValue(ContentProperty, value); }
}public static new readonly DependencyProperty ContentProperty =DependencyProperty.Register("Content", typeof(object), typeof(HorizontalLineContent), new PropertyMetadata(string.Empty));// 箭头方向
public DirectionAlignment Direction
{get { return (DirectionAlignment)GetValue(DirectionProperty); }set { SetValue(DirectionProperty, value); }
}
public static readonly DependencyProperty DirectionProperty =DependencyProperty.Register("Direction", typeof(DirectionAlignment), typeof(HorizontalLineContent), new PropertyMetadata(DirectionAlignment.None));// 文本位置
public ContentDirectionAlignment ContentDirection
{get { return (ContentDirectionAlignment)GetValue(ContentDirectionProperty); }set { SetValue(ContentDirectionProperty, value); }
}
public static readonly DependencyProperty ContentDirectionProperty =DependencyProperty.Register("ContentDirection", typeof(ContentDirectionAlignment), typeof(HorizontalLineContent), new PropertyMetadata(ContentDirectionAlignment.Center));// 直线宽度
public double LineSize
{get { return (double)GetValue(LineSizeProperty); }set { SetValue(LineSizeProperty, value); }
}
public static readonly DependencyProperty LineSizeProperty =DependencyProperty.Register("LineSize", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(4.0));// 箭头宽度
public double ArrowWidth
{get { return (double)GetValue(ArrowWidthProperty); }set { SetValue(ArrowWidthProperty, value); }
}
public static readonly DependencyProperty ArrowWidthProperty =DependencyProperty.Register("ArrowWidth", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(10.0));// 箭头高度
public double ArrowHeight
{get { return (double)GetValue(ArrowHeightProperty); }set { SetValue(ArrowHeightProperty, value); }
}
public static readonly DependencyProperty ArrowHeightProperty =DependencyProperty.Register("ArrowHeight", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(12.0));
添加属性值监听
// 监听整体控件宽度属性变化
ActualWidthPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(Label));
ActualWidthPropertyDescriptor.AddValueChanged(txt_text, (o, e) =>
{RefreshUI();
});// 监听文本内容属性变化
ContentPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentProperty, typeof(HorizontalLineContent));
ContentPropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});// 监听箭头方向属性变化
DirectionPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(DirectionProperty, typeof(HorizontalLineContent));
DirectionPropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});// 监听文本位置属性变化
ContentDirectionPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentDirectionProperty, typeof(HorizontalLineContent));
ContentDirectionPropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});// 监听直线宽度属性变化
LineSizePropertyDescriptor = DependencyPropertyDescriptor.FromProperty(LineSizeProperty, typeof(HorizontalLineContent));
LineSizePropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});// 监听箭头高度属性变化
ArrowHeightPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ArrowHeightProperty, typeof(HorizontalLineContent));
ArrowHeightPropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});// 监听箭头宽度属性变化
ArrowWidthPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ArrowWidthProperty, typeof(HorizontalLineContent));
ArrowWidthPropertyDescriptor.AddValueChanged(this, (o, e) =>
{RefreshUI();
});
获取点数据
public List<Point> GetPoints(DirectionAlignment direction, double left, double mid_left, double mid_right, double right)
{var points = new List<Point>();if (ContentDirection != ContentDirectionAlignment.Center && ContentDirection != ContentDirectionAlignment.None){mid_left = mid_right = this.ActualWidth / 2.0;}var mid_width = this.ActualWidth / 2.0;var lineSize = LineSize < 1 ? 1 : LineSize;var arrowWidth = ArrowWidth < 5 ? 5 : ArrowWidth;var arrowHeight = ArrowHeight < 6 ? 6 : ArrowHeight;if (arrowHeight < lineSize){arrowHeight = lineSize;}var lineSize_0 = 0; // 0var lineSize_1 = arrowHeight / 2.0 - lineSize / 2.0; // 4var lineSize_2 = arrowHeight / 2.0; // 6var lineSize_3 = arrowHeight / 2.0 + lineSize / 2.0; // 8var lineSize_4 = arrowHeight; // 12switch (direction){case DirectionAlignment.None:// Left Pointspoints.Add(new Point(0, lineSize_0));points.Add(new Point(mid_left, lineSize_0));points.Add(new Point(mid_left, lineSize));points.Add(new Point(0, lineSize));// Right Pointspoints.Add(new Point(mid_right, lineSize_0));points.Add(new Point(right, lineSize_0));points.Add(new Point(right, lineSize));points.Add(new Point(mid_right, lineSize));break;case DirectionAlignment.Left:// Left Pointspoints.Add(new Point(mid_left, lineSize_1));points.Add(new Point(arrowWidth, lineSize_1));points.Add(new Point(arrowWidth, lineSize_0));points.Add(new Point(0, lineSize_2));points.Add(new Point(arrowWidth, lineSize_4));points.Add(new Point(arrowWidth, lineSize_3));points.Add(new Point(mid_left, lineSize_3));// Right Pointspoints.Add(new Point(mid_right, lineSize_0));points.Add(new Point(right, lineSize_0));points.Add(new Point(right, lineSize));points.Add(new Point(mid_right, lineSize));break;case DirectionAlignment.Right:// Left Pointspoints.Add(new Point(0, lineSize_0));points.Add(new Point(mid_left, lineSize_0));points.Add(new Point(mid_left, lineSize));points.Add(new Point(0, lineSize));// Right Pointspoints.Add(new Point(mid_right, lineSize_1));points.Add(new Point(right - arrowWidth, lineSize_1));points.Add(new Point(right - arrowWidth, lineSize_0));points.Add(new Point(right, lineSize_2));points.Add(new Point(right - arrowWidth, lineSize_4));points.Add(new Point(right - arrowWidth, lineSize_3));points.Add(new Point(mid_right, lineSize_3));break;}return points;
}
全部代码
共4个文件
HorizontalLineContent.xaml
<Window x:Class="WpfApp3.MainWindow"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:WpfApp3"mc:Ignorable="d" FontFamily="微软雅黑"Title="MainWindow" Height="450" Width="1024"><StackPanel Margin="20"><Grid><TextBlock Grid.Row="0" HorizontalAlignment="Left" Text="客户端"></TextBlock><TextBlock Grid.Row="0" HorizontalAlignment="Right" Text="服务端"></TextBlock></Grid><local:HorizontalLineContent ContentDirection="TopLeft" LineSize="2" ArrowHeight="6" ArrowWidth="5" Direction="Right" Content="文本位置【Top】,直线宽度【2】,箭头方向【None(默认)】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" LineSize="4" ArrowHeight="12" ArrowWidth="10" Direction="Left" Foreground="Red" Content="文本位置【None、Center】,直线宽度【4(默认)】,箭头方向【None】,ArrowHeight【12(默认)】,ArrowWidth【10(默认)】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" ContentDirection="Bottom" Direction="Right" Foreground="Green" Content="文本位置【Bottom】,Foreground【Green】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" FontSize="16" ContentDirection="TopLeft" Direction="Right"><local:HorizontalLineContent.Content><StackPanel Orientation="Horizontal"><TextBlock Text="All Default" VerticalAlignment="Center"></TextBlock><StackPanel Margin="10 0 0 0"><Button Content="【ASN.1】"></Button><Line Height="5"></Line><Button Content="【证书】"></Button></StackPanel></StackPanel></local:HorizontalLineContent.Content></local:HorizontalLineContent></StackPanel>
</Window>
HorizontalLineContent.xaml.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Shapes;#region 文件版本信息
/** 创建者:Zekang Hao* 邮箱:admin@haozekang.com* 创建时间:2024/6/27 15:11:07* 版本:1.0.0.0* 描述:HorizontalLineContent.xaml 的交互逻辑*/
#endregionnamespace WpfApp3
{public partial class HorizontalLineContent : UserControl{private DependencyPropertyDescriptor ActualWidthPropertyDescriptor;private DependencyPropertyDescriptor ContentPropertyDescriptor;private DependencyPropertyDescriptor DirectionPropertyDescriptor;private DependencyPropertyDescriptor ContentDirectionPropertyDescriptor;private DependencyPropertyDescriptor LineSizePropertyDescriptor;private DependencyPropertyDescriptor ArrowWidthPropertyDescriptor;private DependencyPropertyDescriptor ArrowHeightPropertyDescriptor;public new object Content{get { return (string)GetValue(ContentProperty); }set { SetValue(ContentProperty, value); }}public static new readonly DependencyProperty ContentProperty =DependencyProperty.Register("Content", typeof(object), typeof(HorizontalLineContent), new PropertyMetadata(string.Empty));public DirectionAlignment Direction{get { return (DirectionAlignment)GetValue(DirectionProperty); }set { SetValue(DirectionProperty, value); }}// Using a DependencyProperty as the backing store for Direction. This enables animation, styling, binding, etc...public static readonly DependencyProperty DirectionProperty =DependencyProperty.Register("Direction", typeof(DirectionAlignment), typeof(HorizontalLineContent), new PropertyMetadata(DirectionAlignment.None));public ContentDirectionAlignment ContentDirection{get { return (ContentDirectionAlignment)GetValue(ContentDirectionProperty); }set { SetValue(ContentDirectionProperty, value); }}// Using a DependencyProperty as the backing store for TextDirection. This enables animation, styling, binding, etc...public static readonly DependencyProperty ContentDirectionProperty =DependencyProperty.Register("ContentDirection", typeof(ContentDirectionAlignment), typeof(HorizontalLineContent), new PropertyMetadata(ContentDirectionAlignment.Center));public double LineSize{get { return (double)GetValue(LineSizeProperty); }set { SetValue(LineSizeProperty, value); }}// Using a DependencyProperty as the backing store for LineSize. This enables animation, styling, binding, etc...public static readonly DependencyProperty LineSizeProperty =DependencyProperty.Register("LineSize", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(4.0));public double ArrowWidth{get { return (double)GetValue(ArrowWidthProperty); }set { SetValue(ArrowWidthProperty, value); }}// Using a DependencyProperty as the backing store for ArrowWidth. This enables animation, styling, binding, etc...public static readonly DependencyProperty ArrowWidthProperty =DependencyProperty.Register("ArrowWidth", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(10.0));public double ArrowHeight{get { return (double)GetValue(ArrowHeightProperty); }set { SetValue(ArrowHeightProperty, value); }}// Using a DependencyProperty as the backing store for ArrowHeight. This enables animation, styling, binding, etc...public static readonly DependencyProperty ArrowHeightProperty =DependencyProperty.Register("ArrowHeight", typeof(double), typeof(HorizontalLineContent), new PropertyMetadata(12.0));public HorizontalLineContent(){this.DataContext = this;InitializeComponent();txt_text.SetBinding(Label.ContentProperty,new Binding{Path = new PropertyPath(nameof(Content)),UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,Mode = BindingMode.OneWay});txt_text.SetBinding(ForegroundProperty,new Binding{Path = new PropertyPath(nameof(Foreground)),UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,Mode = BindingMode.OneWay});pol_left.SetBinding(Polygon.FillProperty,new Binding{Path = new PropertyPath(nameof(Foreground)),UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,Mode = BindingMode.OneWay});pol_right.SetBinding(Polygon.FillProperty,new Binding{Path = new PropertyPath(nameof(Foreground)),UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,Mode = BindingMode.OneWay});ActualWidthPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(Label));ActualWidthPropertyDescriptor.AddValueChanged(txt_text, (o, e) =>{RefreshUI();});ContentPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentProperty, typeof(HorizontalLineContent));ContentPropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});DirectionPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(DirectionProperty, typeof(HorizontalLineContent));DirectionPropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});ContentDirectionPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentDirectionProperty, typeof(HorizontalLineContent));ContentDirectionPropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});LineSizePropertyDescriptor = DependencyPropertyDescriptor.FromProperty(LineSizeProperty, typeof(HorizontalLineContent));LineSizePropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});ArrowHeightPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ArrowHeightProperty, typeof(HorizontalLineContent));ArrowHeightPropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});ArrowWidthPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ArrowWidthProperty, typeof(HorizontalLineContent));ArrowWidthPropertyDescriptor.AddValueChanged(this, (o, e) =>{RefreshUI();});}private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e){RefreshUI();}private void RefreshUI(){if (pol_left == null || pol_right == null || txt_text == null){return;}double control_middle = this.ActualWidth / 2.0;double txt_width_middle = txt_text.ActualWidth / 2.0;double mid_left = control_middle - txt_width_middle;double mid_right = control_middle + txt_width_middle;if (Direction != DirectionAlignment.None && ContentDirection == ContentDirectionAlignment.Center){if (mid_left < 10){pol_left.Visibility = Visibility.Collapsed;pol_right.Visibility = Visibility.Collapsed;}else{pol_left.Visibility = Visibility.Visible;pol_right.Visibility = Visibility.Visible;}}switch (ContentDirection){case ContentDirectionAlignment.None:case ContentDirectionAlignment.Center:txt_text.Padding = new Thickness(0, 0, 0, 0);txt_text.SetValue(Grid.RowProperty, 1);break;case ContentDirectionAlignment.Top:case ContentDirectionAlignment.TopLeft:case ContentDirectionAlignment.TopRight:if (Direction == DirectionAlignment.None){txt_text.Padding = new Thickness(0, 0, 0, 4);}else{txt_text.Padding = new Thickness(0, 0, 0, 0);}txt_text.SetValue(Grid.RowProperty, 0);break;case ContentDirectionAlignment.Bottom:case ContentDirectionAlignment.BottomLeft:case ContentDirectionAlignment.BottomRight:if (Direction == DirectionAlignment.None){txt_text.Padding = new Thickness(0, 4, 0, 0);}else{txt_text.Padding = new Thickness(0, 0, 0, 0);}txt_text.SetValue(Grid.RowProperty, 2);break;}switch (ContentDirection){case ContentDirectionAlignment.TopLeft:case ContentDirectionAlignment.BottomLeft:txt_text.HorizontalAlignment = HorizontalAlignment.Left;break;case ContentDirectionAlignment.TopRight:case ContentDirectionAlignment.BottomRight:txt_text.HorizontalAlignment = HorizontalAlignment.Right;break;default:txt_text.HorizontalAlignment = HorizontalAlignment.Center;break;}pol_left.Points.Clear();pol_right.Points.Clear();var points = GetPoints(Direction, 0, mid_left, mid_right, this.ActualWidth);if (Direction == DirectionAlignment.None){for ( int i = 0; i < 4; i++){pol_left.Points.Add(points[i]);}for ( int i = 4; i < 8; i++){pol_right.Points.Add(points[i]);}}else if (Direction == DirectionAlignment.Left){for (int i = 0; i < 7; i++){pol_left.Points.Add(points[i]);}for (int i = 7; i < 11; i++){pol_right.Points.Add(points[i]);}}else if(Direction == DirectionAlignment.Right){for (int i = 0; i < 4; i++){pol_left.Points.Add(points[i]);}for (int i = 4; i < 11; i++){pol_right.Points.Add(points[i]);}}}public List<Point> GetPoints(DirectionAlignment direction, double left, double mid_left, double mid_right, double right){var points = new List<Point>();if (ContentDirection != ContentDirectionAlignment.Center && ContentDirection != ContentDirectionAlignment.None){mid_left = mid_right = this.ActualWidth / 2.0;}var mid_width = this.ActualWidth / 2.0;var lineSize = LineSize < 1 ? 1 : LineSize;var arrowWidth = ArrowWidth < 5 ? 5 : ArrowWidth;var arrowHeight = ArrowHeight < 6 ? 6 : ArrowHeight;if (arrowHeight < lineSize){arrowHeight = lineSize;}var lineSize_0 = 0; // 0var lineSize_1 = arrowHeight / 2.0 - lineSize / 2.0; // 4var lineSize_2 = arrowHeight / 2.0; // 6var lineSize_3 = arrowHeight / 2.0 + lineSize / 2.0; // 8var lineSize_4 = arrowHeight; // 12switch (direction){case DirectionAlignment.None:// Left Pointspoints.Add(new Point(0, lineSize_0));points.Add(new Point(mid_left, lineSize_0));points.Add(new Point(mid_left, lineSize));points.Add(new Point(0, lineSize));// Right Pointspoints.Add(new Point(mid_right, lineSize_0));points.Add(new Point(right, lineSize_0));points.Add(new Point(right, lineSize));points.Add(new Point(mid_right, lineSize));break;case DirectionAlignment.Left:// Left Pointspoints.Add(new Point(mid_left, lineSize_1));points.Add(new Point(arrowWidth, lineSize_1));points.Add(new Point(arrowWidth, lineSize_0));points.Add(new Point(0, lineSize_2));points.Add(new Point(arrowWidth, lineSize_4));points.Add(new Point(arrowWidth, lineSize_3));points.Add(new Point(mid_left, lineSize_3));// Right Pointspoints.Add(new Point(mid_right, lineSize_0));points.Add(new Point(right, lineSize_0));points.Add(new Point(right, lineSize));points.Add(new Point(mid_right, lineSize));break;case DirectionAlignment.Right:// Left Pointspoints.Add(new Point(0, lineSize_0));points.Add(new Point(mid_left, lineSize_0));points.Add(new Point(mid_left, lineSize));points.Add(new Point(0, lineSize));// Right Pointspoints.Add(new Point(mid_right, lineSize_1));points.Add(new Point(right - arrowWidth, lineSize_1));points.Add(new Point(right - arrowWidth, lineSize_0));points.Add(new Point(right, lineSize_2));points.Add(new Point(right - arrowWidth, lineSize_4));points.Add(new Point(right - arrowWidth, lineSize_3));points.Add(new Point(mid_right, lineSize_3));break;}return points;}}
}
DirectionAlignment.cs
#region 文件版本信息
/** 创建者:Zekang Hao* 邮箱:admin@haozekang.com* 创建时间:2024/6/27 17:01:16* 版本:1.0.0.0* 描述:*/
#endregionnamespace WpfApp3
{/// <summary>/// 描述/// </summary>public enum DirectionAlignment{None,Left,Right,}
}
ContentDirectionAlignment.cs
#region 文件版本信息
/** 创建者:Zekang Hao* 邮箱:admin@haozekang.com* 创建时间:2024/6/28 11:17:07* 版本:1.0.0.0* 描述:*/
#endregionnamespace WpfApp3
{/// <summary>/// 描述/// </summary>public enum ContentDirectionAlignment{None,Top,Center,Bottom,TopLeft,TopRight,BottomLeft,BottomRight,}
}
使用方法
<Window x:Class="WpfApp3.MainWindow"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:WpfApp3"mc:Ignorable="d" FontFamily="微软雅黑"Title="MainWindow" Height="450" Width="1024"><StackPanel Margin="20"><Grid><TextBlock Grid.Row="0" HorizontalAlignment="Left" Text="客户端"></TextBlock><TextBlock Grid.Row="0" HorizontalAlignment="Right" Text="服务端"></TextBlock></Grid><local:HorizontalLineContent ContentDirection="TopLeft" LineSize="2" ArrowHeight="6" ArrowWidth="5" Direction="Right" Content="文本位置【Top】,直线宽度【2】,箭头方向【None(默认)】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" LineSize="4" ArrowHeight="12" ArrowWidth="10" Direction="Left" Foreground="Red" Content="文本位置【None、Center】,直线宽度【4(默认)】,箭头方向【None】,ArrowHeight【12(默认)】,ArrowWidth【10(默认)】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" ContentDirection="Bottom" Direction="Right" Foreground="Green" Content="文本位置【Bottom】,Foreground【Green】"></local:HorizontalLineContent><local:HorizontalLineContent Margin="0 20 0 0" FontSize="16" ContentDirection="TopLeft" Direction="Right"><local:HorizontalLineContent.Content><StackPanel Orientation="Horizontal"><TextBlock Text="All Default" VerticalAlignment="Center"></TextBlock><StackPanel Margin="10 0 0 0"><Button Content="【ASN.1】"></Button><Line Height="5"></Line><Button Content="【证书】"></Button></StackPanel></StackPanel></local:HorizontalLineContent.Content></local:HorizontalLineContent></StackPanel>
</Window>