WPF 使用装饰器给控件添加遮罩层

今天了解一下Adorner类,这个单词的意思就是装饰器,在wpf里有重要的功能。例如:光标,焦点,高亮文本等。

先看一下今天做成的效果吧:image

Adorner我的理解就是在所有控件的上层,还有一层装饰层。就好比两张重叠平放的纸,上面那张就是装饰层,下面那张画满了我们写的控件和窗体。

主要涉及到的类有Adorner和AdornerDecorator。

对装饰器的解释,如果看的不太懂,可以再去百度一下。

下面就直接看代码吧:

Adorner是个抽象类,所以先继承一个出来,备注在代码里:

public class SimpleAdorner : Adorner
    {
        private UIElement child;
        public SimpleAdorner(UIElement adornedElement) : base(adornedElement)
        {
        }
        //Adorner 直接继承自 FrameworkElement,
        //没有Content和Child属性,
        //自己添加一个,方便向其中添加我们的控件
        public UIElement Child
        {
            get => child;
            set
            {
                if (value == null)
                {
                    RemoveVisualChild(child);
                }
                else
                {
                    AddVisualChild(value);
                }
                child = value;
            }
        }
        //重写VisualChildrenCount 表示此控件只有一个子控件
        protected override int VisualChildrenCount => 1;
        //控件计算大小的时候,我们在装饰层上添加的控件也计算一下大小
        protected override Size ArrangeOverride(Size finalSize)
        {
            child?.Arrange(new Rect(finalSize));
            return finalSize;
        }
        //重写GetVisualChild,返回我们添加的控件
        protected override Visual GetVisualChild(int index)
        {
            if (index == 0 && child != null) return child;
            return base.GetVisualChild(index);
        }
    }

写完这个,我们创建一个窗体,备注也都在代码里:

<Window x:Class="WxDemo.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:WxDemo"
        mc:Ignorable="d"
        Title="Adorner学习" Height="450" Width="800">
    <Grid>
        <!--左侧竖 slider-->
        <Slider Orientation="Vertical" Value="60" Maximum="100" Minimum="30" TickFrequency="12" x:Name="slider2" Margin="20 0 0 0"></Slider>
        <!--中间蓝色背景块-->
        <Border Background="LightBlue" Width="300" Height="300">
            <!--定义装饰层-->
            <AdornerDecorator>
                <Grid>
                    <TextBlock Text="蓝色背景的是Border控件" Foreground="Red" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    <Slider Orientation="Horizontal" Value="60" Maximum="100" Minimum="30" TickFrequency="12" x:Name="slider1"></Slider>
                </Grid>
            </AdornerDecorator>
        </Border>
        <StackPanel HorizontalAlignment="Right" VerticalAlignment="Center">
            <Button Click="Button_Click" >显示主窗体遮罩层</Button>
            <Button Click="Button_Click1">显示Border遮罩层</Button>
        </StackPanel>
    </Grid>
</Window>

此window的后台代码如下:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //显示主窗体遮罩层
            //由于slider2在visualtree的上层找到的AdornerLayer控件是window的AdornerLayer,
            //所以看起来 它就显示在了窗体上
            ShowModal(slider2);
        }
        private void Button_Click1(object sender, RoutedEventArgs e)
        {
            //显示Border遮罩层
            ShowModal(slider1);
        }
        public async void ShowModal(Visual visual)
        {
            //获取visual上面的第一个AdornerLayer
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(visual);
            //创建我们定义的Adorner
            var _adorner = new SimpleAdorner(adornerLayer)
            {
                //添加一个半透明的Border
                Child = new Border()
                {
                    Background = new SolidColorBrush(Color.FromArgb(150, 0, 0, 0)),
                    //border内有一个loading控件,就是前两天文章中创建的那个Loading控件
                    Child = new LoadingCircle()
                    {
                        Width = 40,
                        Height = 40
                    }
                }
            };

            //添加到adornerLayer装饰层上
            adornerLayer.Add(_adorner);
            //等待3秒,模拟耗时操作
            await Task.Delay(3000);
            //移除
            adornerLayer.Remove(_adorner);
        }
    }

全部代码都在上面了,有兴趣的小伙伴可以学习一下哦

 

© 版权声明
THE END
喜欢就支持一下吧
点赞19 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情

    暂无评论内容