[WPF系列]-高级部分 Shadowed TextBox

Download Solution

ShadowedTextBoxExample.zip (70.3 KB)

Usage

<local:ShadowedTextBox Label="First Name" Text="{Binding FirstName}" />

Styles

<Style x:Key="shadowedLabelStyle">
    <Setter Property="TextBlock.Foreground" Value="{x:Static SystemColors.ControlDarkBrush}" />
    <Setter Property="FrameworkElement.Opacity" Value="0.8" />
    <Setter Property="TextBlock.FontSize" Value="12" />
    <Setter Property="TextBlock.FontStyle" Value="Italic" />
    <Setter Property="TextBlock.Margin" Value="8,4,4,4" />
</Style>

<Style TargetType="{x:Type local:ShadowedTextBox}">
    <Setter Property="FontSize" Value="14" />
    <Setter Property="Margin" Value="5,2,2,2" />
    <Setter Property="LabelStyle" Value="{StaticResource shadowedLabelStyle}" />
</Style>

ShadowedTextBox.cs

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace ShadowedTextBoxExample
{
    public class ShadowedTextBox : TextBox
    {
        #region Properties
        public string Label
        {
            get { return (string)GetValue(LabelProperty); }
            set { SetValue(LabelProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Label.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register("Label", typeof(string), typeof(ShadowedTextBox), new UIPropertyMetadata("Label"));

        public Style LabelStyle
        {
            get { return (Style)GetValue(LabelStyleProperty); }
            set { SetValue(LabelStyleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelStyle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelStyleProperty =
            DependencyProperty.Register("LabelStyle", typeof(Style), typeof(ShadowedTextBox), new UIPropertyMetadata(null));


        public bool HasText
        {
            get { return (bool)GetValue(HasTextProperty); }
            private set { SetValue(HasTextPropertyKey, value); }
        }

        private static readonly DependencyPropertyKey HasTextPropertyKey =
            DependencyProperty.RegisterReadOnly("HasText", typeof(bool), typeof(ShadowedTextBox), new PropertyMetadata(false));
        public static readonly DependencyProperty HasTextProperty = HasTextPropertyKey.DependencyProperty;

        #endregion

        public ShadowedTextBox()
            : base()
        {
        }

        AdornerLayer myAdornerLayer;
        AdornerLabel myAdornerLabel;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            myAdornerLayer = AdornerLayer.GetAdornerLayer(this);
            myAdornerLabel = new AdornerLabel(this, this.Label, this.LabelStyle);
            UpdateAdorner(this);

            DependencyPropertyDescriptor focusProp = DependencyPropertyDescriptor.FromProperty(FrameworkElement.IsFocusedProperty, typeof(FrameworkElement));
            if (focusProp != null)
            {
                focusProp.AddValueChanged(this, delegate
                {
                    UpdateAdorner(this);
                });
            }

            DependencyPropertyDescriptor containsTextProp = DependencyPropertyDescriptor.FromProperty(ShadowedTextBox.HasTextProperty, typeof(ShadowedTextBox));
            if (containsTextProp != null)
            {
                containsTextProp.AddValueChanged(this, delegate
                {
                    UpdateAdorner(this);
                });
            }
        }

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            HasText = this.Text != "";

            base.OnTextChanged(e);
        }

        protected override void OnDragEnter(DragEventArgs e)
        {
            myAdornerLayer.RemoveAdorners<AdornerLabel>(this); // requires AdornerExtensions.cs

            base.OnDragEnter(e);
        }

        protected override void OnDragLeave(DragEventArgs e)
        {
            UpdateAdorner(this);

            base.OnDragLeave(e);
        }

        private void UpdateAdorner(FrameworkElement elem)
        {
            if (((ShadowedTextBox)elem).HasText || elem.IsFocused)
            {
                // Hide the Shadowed Label
                this.ToolTip = this.Label;
                myAdornerLayer.RemoveAdorners<AdornerLabel>(elem);  // requires AdornerExtensions.cs
            }
            else
            {
                // Show the Shadowed Label
                this.ToolTip = null;
                if (!myAdornerLayer.Contains<AdornerLabel>(elem))  // requires AdornerExtensions.cs
                    myAdornerLayer.Add(myAdornerLabel);
            }
        }
    }
}
posted @   霍旭东  阅读(343)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示