Adorner 装饰器

Posted t-arf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Adorner 装饰器相关的知识,希望对你有一定的参考价值。

装饰器 Adorner

装饰器是WPF中较为常用的技术之一,也是不同于XAML的技术。

较为特殊。

特殊于装饰器全部由C#构成,不同于ControlTenmpate和Style的元素。

装饰器在某些方面能够简化前两者的代码量。

 

现在简单的说一下装饰器的入门用法(通常用法和附加属性一起使用

Adorner是一个抽象类。

由于显示装饰器的方式有两种

 

  1. 直接装载现有WPF控件

  2. 绘制控件

 


 

直接装载现有控件:

         这种方法需要重载四个Adorner方法

  • GetVisualChild //获取Visual的子控件索引
  • ArrangeOverride //确定装饰器的定位
  • MeasureOverride //确定装饰器要约束道德大小
  • VisualChildrenCount//获取VisualCollection的集合数量

 

重写之后就是

编写 私有的VsualCollection来存储你要装载的控件。 

然后利用MeasureOverride和ArrangeOverride这两个方法来进行定位和约束大小。

下面的代码是 可以随时更新内容的装饰器

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

namespace 装饰器
{
    public class TestAdorner : Adorner
    {

        private Grid _Grid;
        private Ellipse _Ellipse;
        private TextBlock _TextBlock;
        private VisualCollection collection;
        private UIElement _UIElement;

        public void UPDATE(string Text)
        {
            var grid = collection[0] as Grid;

            (grid.Children[1] as TextBlock).Text=Text;

        }
        public TestAdorner(UIElement adornedElement) : base(adornedElement)
        {
            collection = new VisualCollection(this);

            _Grid = new Grid()
            {
                Width=20
                ,
                Height=20
                
            };
_Ellipse
= new Ellipse() { Fill = new SolidColorBrush(Colors.Red) };
_TextBlock
= new TextBlock() { HorizontalAlignment = HorizontalAlignment.Center , VerticalAlignment = VerticalAlignment.Center , FontSize=15 }; _Grid.Children.Add(_Ellipse); _Grid.Children.Add(_TextBlock); collection.Add(_Grid); _UIElement = adornedElement; } protected override int VisualChildrenCount => collection.Count; protected override Visual GetVisualChild(int index) => collection[index]; protected override Size MeasureOverride(Size constraint) => base.MeasureOverride(constraint); protected override Size ArrangeOverride(Size finalSize) { _Grid.Arrange(new Rect(finalSize));
_Grid.Margin
= new Thickness((_UIElement as Button).ActualWidth-30, 0, 0, (_UIElement as Button).ActualHeight-30);
return base.ArrangeOverride(finalSize); } } }

 

XAML页面

    <Grid>
        <Button x:Name="TestBtn" Content="选中" Loaded="A_Loaded"  Height="100" Width="300"/>         
    </Grid>

 

CS页面

namespace 装饰器
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        AdornerLayer layer;

        DispatcherTimer timer;

        public MainWindow()
        {
            InitializeComponent();
timer
= new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000) };
timer.Tick
+= Timer_Tick; }

private void Timer_Tick(object sender, EventArgs e) { if (i == 1000) timer.Stop();
var b= layer.GetAdorners(TestBtn) ?? null;
if(b!=null) { var k=b[0] as TestAdorner;
k.UPDATE(i.ToString()); }
else { var j = new TestAdorner(TestBtn);
j.UPDATE(
0.ToString());
layer.Add(j); } i
++; } int i = 0; private void A_Loaded(object sender, RoutedEventArgs e) {
layer
= AdornerLayer.GetAdornerLayer(TestBtn);
timer.Start();
} } }

效果图

技术分享图片

 


 

 

绘制控件

绘制需要重载一个方法就好了

  •  OnRender//绘制控件

 

不过值得注意的是,绘制方式无法更新。至少我是不会。

现在给出代码

namespace 装饰器
{
    public class TestAdornerOnRender : Adorner
    {

        public TestAdornerOnRender(UIElement adornedElement) : base(adornedElement) { }


        protected override void OnRender(DrawingContext drawingContext)
        {

            FormattedText t = new FormattedText(
             "!!!!!",
             CultureInfo.InstalledUICulture,
             FlowDirection.LeftToRight,
             new Typeface("微软雅黑"),
             15, new SolidColorBrush(Colors.Red)
            );
            drawingContext.DrawText(t, new Point(270, 0));
            base.OnRender(drawingContext);
        }


    }
}

 

xaml页面

<Grid>
        <Button x:Name="TestBtn" Content="选中" Loaded="A_Loaded"  Height="100" Width="300">
            
        </Button>
    </Grid>

 

cs 页面

 private void A_Loaded(object sender, RoutedEventArgs e)
        {
           var  layer = AdornerLayer.GetAdornerLayer(TestBtn);

            layer.Add(new TestAdornerOnRender(TestBtn));
            
          
        }

 

截图

技术分享图片



















以上是关于Adorner 装饰器的主要内容,如果未能解决你的问题,请参考以下文章

在 ScrollViewer 可滚动区域中包含 Adorner

WPF和Expression Blend开发实例:Adorner(装饰器)应用实例

WPF 基于Adorner实现类似Popup效果

如何在 WPF 自定义装饰器中用线条排列拇指

如何在 ScrollViewer 中获得 Adorner 与其装饰元素的一对一匹配?

python使用上下文对代码片段进行计时,非装饰器