WPF 实现蒙板控件
- 框架使用
.NET40
; Visual Studio 2022
;- 使用方式需引入命名空间后
wd:Mask.IsMask="true"
,即可显示蒙板。 - 显示蒙板内容需
wd:Mask.Child
进行复赋值。
实现代码
1)创建装饰 AdornerContainer
代码如下:
using System.Windows; using System.Windows.Documents; using System.Windows.Media; namespace WPFDevelopers.Utilities { public class AdornerContainer : Adorner { private UIElement _child; public AdornerContainer(UIElement adornedElement) : base(adornedElement) { } public UIElement Child { get => _child; set { if (value == null) { RemoveVisualChild(_child); _child = value; return; } AddVisualChild(value); _child = value; } } protected override int VisualChildrenCount { get { return _child != null ? 1 : 0; } } protected override Size ArrangeOverride(Size finalSize) { _child?.Arrange(new Rect(finalSize)); return finalSize; } protected override Visual GetVisualChild(int index) { if (index == 0 && _child != null) return _child; return base.GetVisualChild(index); } } }
2)创建蒙板控件 MaskControl
代码如下:
using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace WPFDevelopers.Controls { public class MaskControl : ContentControl { private readonly Visual visual; public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MaskControl), new PropertyMetadata(new CornerRadius(0))); public MaskControl(Visual _visual) { visual = _visual; } public CornerRadius CornerRadius { get => (CornerRadius)GetValue(CornerRadiusProperty); set => SetValue(CornerRadiusProperty, value); } } }
3)创建 Mask
继承 Control
增加附加属性 IsMask
代码如下:
True
则动态添加装饰器AdornerContainer
并将MaskControl
添加到AdornerContainer.Child
中。False
则移除装饰器。
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using WPFDevelopers.Helpers; using WPFDevelopers.Utilities; namespace WPFDevelopers.Controls { public class Mask : Control { public object Child { get { return (object)GetValue(ChildProperty); } set { SetValue(ChildProperty, value); } } public static readonly DependencyProperty ChildProperty = DependencyProperty.Register("Child", typeof(object), typeof(Mask), new PropertyMetadata(null)); public static object GetChild(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (object)element.GetValue(ChildProperty); } public static void SetChild(UIElement element, object child) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(ChildProperty, child); } public static readonly DependencyProperty IsMaskProperty = DependencyProperty.RegisterAttached("IsMask", typeof(bool), typeof(Mask), new PropertyMetadata(false, OnIsMaskChanged)); private static void OnIsMaskChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { PropertyChanged(d, e); } static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.NewValue is bool isMask && d is FrameworkElement parent) { if (isMask) { if (!parent.IsLoaded) parent.Loaded += Parent_Loaded; else CreateMask(parent); } else { parent.Loaded -= Parent_Loaded; CreateMask(parent, true); } } } private static void Parent_Loaded(object sender, RoutedEventArgs e) { if (sender is UIElement element) CreateMask(element); } static void CreateMask(UIElement uIElement, bool isRemove = false) { var _layer = AdornerLayer.GetAdornerLayer(uIElement); if (_layer == null) return; if (isRemove && uIElement != null) { var adorners = _layer.GetAdorners(uIElement); if (adorners != null) { foreach (var item in adorners) { if (item is AdornerContainer container) { _layer.Remove(container); } } } return; } var _adornerContainer = new AdornerContainer(uIElement); var value = Mask.GetChild(uIElement); _adornerContainer.Child = new MaskControl(uIElement) { Content = value }; _layer.Add(_adornerContainer); } public static bool GetIsMask(DependencyObject obj) { return (bool)obj.GetValue(IsMaskProperty); } public static void SetIsMask(DependencyObject obj, bool value) { obj.SetValue(IsMaskProperty, value); } } }
4)创建 Mask.xaml
代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:WPFDevelopers.Controls"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Basic/ControlBasic.xaml"/> </ResourceDictionary.MergedDictionaries> <Style TargetType="{x:Type controls:MaskControl}" BasedOn="{StaticResource ControlBasicStyle}"> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Background" Value="{DynamicResource PrimaryTextSolidColorBrush}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type controls:MaskControl}"> <controls:SmallPanel> <Border x:Name="PART_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Height}" CornerRadius="{TemplateBinding CornerRadius}" Opacity=".7"/> <ContentPresenter Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> </controls:SmallPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
5)创建 MaskExample.xaml
实例代码如下:
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.MaskExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid Margin="10"> <StackPanel> <ToggleButton Name="ToggleButtonMask"/> <Border Background="LawnGreen" Height="200" wd:Mask.IsMask="{Binding ElementName=ToggleButtonMask,Path=IsChecked}" Margin="10"> <wd:Mask.Child> <Border> <TextBox wd:ElementHelper.IsWatermark="True" wd:ElementHelper.Watermark="我是蒙板输入框"/> </Border> </wd:Mask.Child> <Button Content="Mask" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Border> </StackPanel> </Grid> </UserControl>
效果图
以上就是基于WPF实现蒙板控件的示例代码的详细内容,更多关于WPF蒙板控件的资料请关注其它相关文章!