水印控件

用装饰器实现,装饰器最大的好处就是不影响控件原本的表现的基础之上增加一些显示的效果,而且利于扩展。

通过扩展控件也能实现,但是部分控件是密封的,比如PasswordBox,而且还需要修改样式是比较麻烦费力;

效果

WatermarkAdorner:定义了附加属性、在Text的附加属性的OnTextChanged中给对应的控件的加载事件添加了Adorner(利用反射消除控件类型及对应的控件装饰器的判断)

    /// <summary>
    /// 水印装饰器
    /// </summary>
    public class WatermarkAdorner : Adorner
    {
        public WatermarkAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            IsHitTestVisible = false; //不可命中
            InvalidateVisual();
        }

        //强制布局发生改变,根据当前信息实时绘制
        protected void Adorner_RoutedEvent(object sender, RoutedEventArgs e)
        {
            InvalidateVisual();
        }

        #region 附加属性

        public static Thickness GetMargin(DependencyObject obj)
        {
            return (Thickness)obj.GetValue(MarginProperty);
        }

        public static void SetMargin(DependencyObject obj, Thickness value)
        {
            obj.SetValue(MarginProperty, value);
        }

        public new readonly static DependencyProperty MarginProperty =
            DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(WatermarkAdorner), new PropertyMetadata(new Thickness(0)));

        public static string GetText(DependencyObject obj)
        {
            return (string)obj.GetValue(TextProperty);
        }

        public static void SetText(DependencyObject obj, string value)
        {
            obj.SetValue(TextProperty, value);
        }

        /// <summary>
        /// 文本属性
        /// </summary>
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.RegisterAttached("Text", typeof(string), typeof(WatermarkAdorner), new PropertyMetadata(string.Empty, OnTextChanged));

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if (element != null)
            {
                WatermarkAdorner adorner = new WatermarkAdorner(element);
                WatermarkAdorner watermarkAdorner = null;
                Type type = adorner.GetType();
                Assembly assembly = type.Assembly;
                watermarkAdorner = (WatermarkAdorner)assembly.CreateInstance(type.Namespace + "." + element.GetType().Name + "WatermarkAdorner", false, BindingFlags.CreateInstance, null, new object[] { element }, CultureInfo.CurrentCulture, null);

                element.Loaded += (sender, arg) =>
                {
                    if (watermarkAdorner != null)
                    {
                        AdornerLayer.GetAdornerLayer(element).Add(watermarkAdorner);
                    }
                };
            }
        }

        public static Brush GetForeground(DependencyObject obj)
        {
            return (Brush)obj.GetValue(ForegroundProperty);
        }

        public static void SetForeground(DependencyObject obj, Brush value)
        {
            obj.SetValue(ForegroundProperty, value);
        }

        /// <summary>
        /// 前景色
        /// </summary>
        public static readonly DependencyProperty ForegroundProperty =
            DependencyProperty.RegisterAttached("Foreground", typeof(Brush), typeof(WatermarkAdorner), new UIPropertyMetadata(Brushes.Gray));

        public static Brush GetBackground(DependencyObject obj)
        {
            return (Brush)obj.GetValue(BackgroundProperty);
        }

        public static void SetBackground(DependencyObject obj, Brush value)
        {
            obj.SetValue(BackgroundProperty, value);
        }

        /// <summary>
        /// 背景色
        /// </summary>
        public static readonly DependencyProperty BackgroundProperty =
            DependencyProperty.RegisterAttached("Background", typeof(Brush), typeof(WatermarkAdorner), new UIPropertyMetadata(Brushes.Transparent));

        public static FontStyle GetFontStyle(DependencyObject obj)
        {
            return (FontStyle)obj.GetValue(FontStyleProperty);
        }

        public static void SetFontStyle(DependencyObject obj, FontStyle value)
        {
            obj.SetValue(FontStyleProperty, value);
        }

        /// <summary>
        /// 字体风格
        /// </summary>
        public static readonly DependencyProperty FontStyleProperty =
            DependencyProperty.RegisterAttached("FontStyle", typeof(FontStyle), typeof(WatermarkAdorner), new UIPropertyMetadata(FontStyles.Italic));

        #endregion
    }
}

TextBoxWatermarkAdorner:构造函数为控件的对应事件订阅刷新水印事件、OnRender方法判断是否满足添加水印的条件以及绘制水印

    public class TextBoxWatermarkAdorner : WatermarkAdorner
    {

        //被装饰的文本输入框
        private readonly TextBox _adornerTextBox;
        public TextBoxWatermarkAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            var adornerTextBox = adornedElement as TextBox;
            if (adornerTextBox != null)
            {
                _adornerTextBox = adornerTextBox;
                _adornerTextBox.LostFocus += Adorner_RoutedEvent;
                _adornerTextBox.GotFocus += Adorner_RoutedEvent;
                _adornerTextBox.TextChanged += Adorner_RoutedEvent;
            }
            InvalidateVisual();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (_adornerTextBox != null && (!_adornerTextBox.IsFocused && string.IsNullOrEmpty(_adornerTextBox.Text)))
            {
                FormattedText formattedText =
                    new FormattedText(
                        GetText(_adornerTextBox),
                        CultureInfo.CurrentUICulture,
                        _adornerTextBox.FlowDirection,
                        _adornerTextBox.FontFamily.GetTypefaces().FirstOrDefault(),
                        _adornerTextBox.FontSize,
                        GetForeground(_adornerTextBox));
                formattedText.SetFontStyle(GetFontStyle(_adornerTextBox));

                drawingContext.DrawText(formattedText,
                    new Point(GetMargin(_adornerTextBox).Left, GetMargin(_adornerTextBox).Left));
            }
        }
    }

PasswordBoxWatermarkAdorner:构造函数为控件的对应事件订阅刷新水印事件、OnRender方法判断是否满足添加水印的条件以及绘制水印

    public class PasswordBoxWatermarkAdorner : WatermarkAdorner
    {
        private readonly PasswordBox _adornedPasswordBox;

        public PasswordBoxWatermarkAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            var passwordBox = adornedElement as PasswordBox;
            if (passwordBox != null)
            {
                _adornedPasswordBox = passwordBox;
                _adornedPasswordBox.LostFocus += Adorner_RoutedEvent;
                _adornedPasswordBox.GotFocus += Adorner_RoutedEvent;
                _adornedPasswordBox.PasswordChanged += Adorner_RoutedEvent;
            }
            InvalidateVisual();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (_adornedPasswordBox != null && (_adornedPasswordBox.IsFocused || !string.IsNullOrEmpty(_adornedPasswordBox.Password)))
                return;

            FormattedText formatted = new FormattedText(GetText(_adornedPasswordBox), CultureInfo.CurrentCulture,
                GetFlowDirection(_adornedPasswordBox), _adornedPasswordBox.FontFamily.GetTypefaces().FirstOrDefault(),
                _adornedPasswordBox.FontSize, GetForeground(_adornedPasswordBox));

            formatted.SetFontStyle(GetFontStyle(_adornedPasswordBox));

            drawingContext.DrawText(formatted,
                new Point(GetMargin(_adornedPasswordBox).Left, GetMargin(_adornedPasswordBox).Top));
        }
    }

界面使用

<Window x:Class="Watermarker.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Watermarker"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBox Height="40" Width="100"
                 FontSize="18"
                 local:TextBoxWatermarkAdorner.Text="请输入文本"
                 local:TextBoxWatermarkAdorner.Margin="5,5,0,0"/>
        <PasswordBox Height="40" Width="100"
                     local:PasswordBoxWatermarkAdorner.Text="请输入密码"
                     local:PasswordBoxWatermarkAdorner.Margin="5,5,0,0"/>
    </StackPanel>
</Window>
时间: 2024-11-18 05:32:24

水印控件的相关文章

WPF 自定义TextBox带水印控件,可设置圆角

一.简单设置水印TextBox控件,废话不多说看代码: <TextBox TextWrapping="Wrap" Margin="10" Height="69" Visibility="Visible"> <TextBox.Style> <Style TargetType="TextBox"> <Style.Triggers> <MultiTrigger

AJAX 控件集之TextBoxWatermark(水印文本框)控件

功能:       可以让TextBox控件初始化的时候拥有水印文字.属性:    TargetControlID :要使用具有水印效果的TextBox控件ID.    WatermarkCssClass :指定水印文字的CSS样式表.    WatermarkText :显示在TextBox控件的水印文字内容. 代码实例: <asp:Panel ID="panIntTemp" runat="server" GroupingText="新增资料&qu

Winform控件的水印效果制作

在我们的项目中,为控件绘制水印效果是十分常见的事情,下面我就来说说水印效果的制作方式.其实在绝大多数情况下只有下拉框和输入框多会使用水印,比如我们看到的新浪邮箱,(如:图1).下面是输入框水印效果的代码实现:using System.Drawing;using System.Windows.Forms;namespace TextBoxWithWaterkmarkExample{ /// <summary> /// 带水印效果的TextBox /// </summary>    p

C# WinForm控件美化扩展系列之给TextBox加水印

在一些软件中,我们看到当一个输入控件(textbox)没有输入而且没有焦点的时候,会显示一些提示信息,网上有一些介绍用复合控件来实现,其实我们直接继承textbox控件也很容易实现. 下面就介绍怎样来实现这个控件. 第一步:我们建一个继承 textbox 的类,命名为watermaktextbox. 第二步:给这个类添加两个属性,一个是emptytexttip,就是当控件没有输入内容和没有焦点的时候显示的提示文本,也就是水印了:另一个是emptytexttipcolor,就是提示文本的颜色. 第

(七十五)c#Winform自定义控件-控件水印组件

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  麻烦博客下方点个[推荐],谢谢 NuGet Install-Package HZH_Con

收集Github上的iOS控件和开发资料

文章来源:http://www.mobile-open.com/2015/85017.html 动画 awesome-ios-animation 收集了iOS平台下比较主流炫酷的几款动画框架 RCTRefreshControl qq的下拉刷新 TBIconTransitionKit icon 的点击动画过渡效果 PullToBounce 类似百度外卖的下拉刷新动画 LiquidFloatingActionButton 可定制水滴型浮动动态按钮组件及演示 富文本 DDRichText 附带了微信朋

Windows应用程序文件格式转换控件LEADTOOLS ePrint Professional

LEADTOOLS ePrint Professional控件是一个多功能一体化文件转换解决方案,它可帮助您将任何Windows应用程序中的文件或图像转换为150种类型的文件,其中包括:PDF, DOC, HTML, TXT, TIFF, JPG, GIF, PNG等等. ePrint Professional包含了两种转换模式 - ePrint printer和ePrint Workstation printer,为您提供不同水平的文件转换控制,您可以更加灵活的进行生产.ePrint prin

支持Word文档和其他文件格式间的转换的控件Spire.Doc for .NET

Spire.Doc for .NET是e-iceblue公司推出的一款专门对Microsoft Word 文档进行操作的.NET类控件.这款控件的主要功能在于帮助开发人员轻松快捷地生成.编辑和查看Word文档.同时,开发人员还可以通过使用Spire.Doc for .NET 设置Word文档的格式,插入图片,表格,超链接等.Spire.Doc for .NET 最大的便利之处在于它不依赖于Microsoft Word以及任何其他第三方软件.只需将此款控件安装在您的电脑上,您就可以对word文档进

activePDF Architect WBE 控件可动态产生自定义PDF文件,控制布局和页面元素

activePDF Architect WBE 控件提供了强健的API用于即时地构建完美的PDF报表.PDF表单等,可以添加文本.图像.表格.注释.表单字段等,并且可以完全控制格式和布局位置,直接从你应用程序产生高质量的PDF文档. 具体功能: 动态产生自定义PDF文件,控制布局和页面元素 从头开始构建PDF,使用强健的表格控件和其他工具创建专业的适合你商业标准的布局 整合交互式元素到PDF里,如超链接.表单字段.注释等 直接从应用程序或者数据库数据,快速且简便地创建大批量PDF文件 使用相似的