XAMLを使わないWPF入門42「UIに重ねて装飾する仕組み – Adorner」

コンピュータ

Adornerを使うと既存のコントロールを装飾することが出来ます。

サンプルコードのプロジェクトの作成

ボタンに赤枠

最小サンプルとしてAdornerボタンに赤い枠を装飾してみます。

ソースコード

ファイル名:AppEntry.cs

using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Controls;

namespace NoXAML42Adorner01;
public class BorderAdorner : Adorner
{
    public BorderAdorner(UIElement adornedElement) : base(adornedElement) { }

    protected override void OnRender(DrawingContext dc)
    {
        var rect = new Rect(this.AdornedElement.RenderSize);
        dc.DrawRectangle(null, new Pen(Brushes.Red, 2), rect);
    }
}

public class App : Application
{
    [System.STAThread]
    public static void Main()
    {
        var app = new App();
        var win = new Window { Width = 300, Height = 200 };

        var btn = new Button { Content = "Hello", Width = 100, Height = 50, Margin = new Thickness(50) };
        win.Content = btn;

        win.Loaded += (_, __) =>
        {
            var layer = AdornerLayer.GetAdornerLayer(btn);
            layer.Add(new BorderAdorner(btn));
        };

        app.Run(win);
    }
}

実行例

image

コントロールのサイズを動的に変更

ボタンのサイズを変更します。

ソースコード

ファイル名:AppEntry.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Media;

namespace NoXAML42Adorner01;
public class ResizeAdorner : Adorner
{
    private readonly Thumb bottomRight;

    public ResizeAdorner(UIElement adornedElement) : base(adornedElement)
    {
        bottomRight = new Thumb
        {
            Width = 10,
            Height = 10,
            Background = Brushes.Blue,
            Cursor = System.Windows.Input.Cursors.SizeNWSE
        };

        bottomRight.DragDelta += (s, e) =>
        {
            if (AdornedElement is FrameworkElement fe)
            {
                fe.Width = Math.Max(fe.Width + e.HorizontalChange, 20);
                fe.Height = Math.Max(fe.Height + e.VerticalChange, 20);
            }
        };

        AddVisualChild(bottomRight);
    }

    protected override int VisualChildrenCount => 1;
    protected override Visual GetVisualChild(int index) => bottomRight;

    protected override Size ArrangeOverride(Size finalSize)
    {
        double w = AdornedElement.RenderSize.Width;
        double h = AdornedElement.RenderSize.Height;
        bottomRight.Arrange(new Rect(w - 5, h - 5, 10, 10));
        return finalSize;
    }
}

public class App : Application
{
    [System.STAThread]
    public static void Main()
    {
        var app = new App();
        var win = new Window { Width = 400, Height = 300 };

        var rect = new Border
        {
            Background = Brushes.LightGray,
            Width = 100,
            Height = 80,
            Margin = new Thickness(50)
        };
        win.Content = rect;

        win.Loaded += (_, __) =>
        {
            var layer = AdornerLayer.GetAdornerLayer(rect);
            layer.Add(new ResizeAdorner(rect));
        };

        app.Run(win);
    }
}

実行例

コメント