天天看點

使用Adorner顯示WPF控件的邊界點

原文:

使用Adorner顯示WPF控件的邊界點

當我們拖動WPF控件時,我們為了更清楚地需要顯示控件,一般我們會在WPF控件所圍成的矩形區域的四個邊界點上作一個特殊的記号(比如圓點)。如下圖:

使用Adorner顯示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.Windows.Controls;

using System.Windows.Data;

using System.Windows.Shapes;

using System.Collections;

  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)

  }

注意:這裡使用AdornerLayer.Add(new CircleAdorner(UIElement))方法來完成這種附加。