当我们拖动WPF控件时,我们为了更清楚地需要显示控件,一般我们会在WPF控件所围成的矩形区域的四个边界点上作一个特殊的记号(比如圆点)。如下图:
WPF中显示控件的边界点

在Winform中,我们一般都是先找到控件所包围的矩形区域,然后画出四个边界点。那么,在WPF,如何显示这四个边界点呢?

答案是使用Adorner。Adorner是继承自FrameworkElement的抽象类:
public abstract class Adorner : FrameworkElement

首先,我们建立一个CircleAdorner类,它继承自Adorner:
//CircleAdorner.cs
using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace BrawDraw.Com.WPF
{
public class CircleAdorner : Adorner
{
public CircleAdorner(UIElement adornedElement)
: base(adornedElement)
{
}

protected override void OnRender (DrawingContext drawingContext)
{
//找出控件所围成的矩形区域
Rect adornedElementRect = new Rect( this.AdornedElement.DesiredSize );
SolidColorBrush renderBrush = new SolidColorBrush(Colors.Red);
renderBrush.Opacity = 1.0;
Pen renderPen = new Pen(new SolidColorBrush(Colors.Red), 0.5);
double renderRadius = 3.0;

drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius);
drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius);
drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius);
drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius);
}
}
}

上面这个类的作用是对相应控件的“附加绘制”,它画出控件的四个顶点。这里的OnRender相当于GDI+中的OnPaint。

下面我们对一个TextBox,一个包含于StackPanel中的Button和TextBox, 以及包含于Canvas中的Path进行“附加绘制”。

先看看XAML代码:
// Window1.xaml
<Window x:Class="BrawDraw.Com.WPF.Window1"
xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml "
Title="CircleAdornerDemo" Loaded="WindowLoaded" Height="464" Width="625"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox
Name="myTextBox"
Height="50" Width="150"
Grid.Row="0"
Text="这是一个TextBox."
/>
<StackPanel Name="myStackPanel" Grid.Row="1">
<Button
Name="myButton1"
Width="150"
Content="Adorned Button"
/>
<TextBox Grid.Row="1" Name="textBox1" Height="100" Width="220" />
</StackPanel>
<Canvas Margin="51,141,162,59"  Name="myCanvas" Grid.Row="1">
<Path StrokeThickness="1.000000" Stroke="#fffa0e0b" StrokeMiterLimit="1.000000" Data="F1 M 100.295898,66.248535 C 100.295898,66.248535 44.894531,33.529785 68.517578,66.316895 C 92.140137,99.104004 197.243164,6.331055 274.625000,133.188477 C 366.679688,46.227051 378.309570,2.718750 359.714844,25.067383"/>
</Canvas>
</Grid>
</Window>

下面是控制代码:
// Window1.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Collections;

namespace BrawDraw.Com.WPF
{

public partial class Window1 : Window
{
AdornerLayer myAdornerLayer;

public Window1()
{
InitializeComponent();
}

private void WindowLoaded(object sender, RoutedEventArgs e)
{
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add( new CircleAdorner(myTextBox) );

foreach (UIElement toAdorn in myStackPanel.Children)
{
myAdornerLayer.Add(new CircleAdorner(toAdorn));
}

foreach (UIElement toAdorn in myCanvas.Children)
{
myAdornerLayer.Add(new CircleAdorner(toAdorn));
}
}
}
}

注意:这里使用 AdornerLayer.Add( new CircleAdorner(UIElement) 方法来完成这种附加。

关于 WPF 系列 Ado rner 的学习笔记。 Ado rner WPF 中的界面设计中很常见,它可以用来实现更加美观的界面视觉效果,也可以设计事件动态效果等等。 1.在界面元素上提供视觉效果,以提示用户当前元素处于特定状态。 2.从视觉上遮盖或重写UIElement的一部分或全部 3.向UIElement添加功能控点, 使用 户可以操作元素(调整大小、旋转、重新定位等) 4.作为 控件 的附加属性来控制 控件 外观 显示 的变化 具体请参考本博客文章! 关于 WPF 系列 Ado rner 的学习笔记。 Ado rner WPF 中的界面设计中很常见,它可以用来实现更加美观的界面视觉效果,也可以设计事件动态效果等等。 Ado rner ,抽象基类,所有具有装饰器的实现都从该类继承; Ado rner ,是一种特殊类型的FrameworkElement,用于向用户提供可视化提示; Ado rner ,简单地说,就是 WPF 装饰器,作用是给 WPF 控件 上一层装饰效果; Ado rner ,是 WPF 窗口中独立的一层,支持在界面元素之上执行独立的绘制及用户交互; 装饰器可以用来给 显示 控件 添加一些装饰的效果;首先添加一个装饰器类:Test Ado rner 。(为下面的Button四周添加了小圆圈效果)(给 控件 周围添加了四个红框)   看到这个标题,您可能会在脑中产生一个疑问: Ado rner 是什么? Ado rner WPF 窗口中独立的一层,支持在界面元素之上执行独立的绘制及用户交互。可以说, Ado rner 在您的 WPF 程序中无处不在。在 WPF 中,从编辑框 控件 中光标的 显示 和选中效果的支持,到具有数据焦点的 控件 所具有的虚线外框,都是通过 Ado rner 实现的。 什么是 Ado rner 鉴于您可能不熟悉 Ado rne... 它们都有“装饰品”的意思。 Decorator类负责包装某个UI元素,以提供额外的行为。它有一个类型为UIElement的Child属性,其中含有待包装的内容。Decorator可被用于添加简单的视觉装饰,例如边界(Border),或者更复杂的行为,例如ViewBox, Ado rner Decorator,或是InkPresenter。 当你从Decora... 在 WPF 界面设计中, Ado rner 可以为好的界面锦上添花, 使用 它的方式很多,现在 WPF 的设计模式一般是MVVM,为了满足需求,可以通过以下两种方式控制 Ado rner 。    1. 使用 附加属性控制 Ado rner :     添加一个类,其中包含一个依赖属性,以及一个设置 Ado rner 的方法,依赖属性代码如下: public static re ado nly DependencyPro 项目中有时需要在图片上标注热区,在HTML中有<area>标签,但在 WPF 中目前还没现成的 控件 来实现这这一功能。至于图片热区功能有道词典的【图解词典】是个不错的例子,如图1: 什么是 Ado rner Ado ner 是一个绑定到某个UIElement自定义的FrameWorkElemnt 。 Ado ner被渲染在 Ado rner Layer,而 Ado rner Lay... // 边缘检测:Roberts public static ImageSource GrayDataToImageEdgeRoberts(this ushort[,] grayData, int[,] colorMap, int maxValue = 65535)