[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);
            }
        }
    }
}
时间: 2024-08-10 10:22:26

[WPF系列]-高级部分 Shadowed TextBox的相关文章

[WPF系列-高级TemplateBinding vs RelativeSource TemplatedParent]

What is the difference between these 2 bindings: <ControlTemplate TargetType="{x:Type Button}"> <Border BorderBrush="{TemplateBinding Property=Background}"> <ContentPresenter /> </Border> </ControlTemplate>

[WPF系列] 高级 调试

ImageBrush出现TypeConverter问题 'Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.' Line number '49' and line position '38'   Assuming the image is: Included in your project It's in a folder named "Images" T

[WPF系列]-高级部分 需要区分的东东

ContentControl VS ContentPresenter What's the difference between ContentControl and ContentPresenter? ContentPresenter is usually used in a ControlTemplate, as a placeholder to say "put the actual content here". A ContentControl can be used anyw

【WPF系列】Textbox

Style <Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}"> <Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="OverridesDefaultStyle" Value="True"/>

WPF自定义控件与样式(3)-TextBox &amp; RichTextBox &amp; PasswordBox样式、水印、Label标签、功能扩展

原文:WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式.水印.Label标签.功能扩展 一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本输入控件进行样式开发,及相关扩展功能开发,主要内容包括: 基本文本框TextBox控件样式及扩展功能,实现了样式.水印.Label标签.功能扩展: 富

自学WPF系列(1)

介绍 使用WPF工作6个多月了,是时候写一些WPF的基础知识了.在这个主题上我已经写了几篇文章了.他们都是基于处理一些具体的问题而完成的.现在我抛砖引玉,并让您理解如何/为什么WPF作为革命性的UI开发走向了我们. 由于这是一篇适合初学者和中级水平的程序员的文章,我将尽量给出尽可能多的基本的例子. Windows Presectation Foundation 正如名字所示,WPF实际上是.NET Framework3.0引入的几个framework.它实际上是提出了一套新的类和程序集并允许我们

WPF系列之二:解耦View层控件事件与ViewModel层事件的响应

以前的做法: 1.当项目的时间比较紧迫的时候,对UI层中控件的事件的处理,往往采取的是类似Winform中最简单的做法,直接做一个事件的Handler直接去调用VM层的方法. 2.控件只有一个Command属性,其它的事件的处理方法没有办法和ViewModel层进行解耦的时候往往也采取上面提到的方法. 如下图所示: 新的做法: 为了实现事件的处理与View层的解耦,我们可以利用WPF提供的附加属性来为需要的事件添加附加行为.附加属性扮演了一个在View层与Model层牵线的角色. 需要下面三个步

WPF系列之三:实现类型安全的INotifyPropertyChanged接口,可以不用“Magic string” 么?

通常实现INotifyPropertyChanged接口很简单,为你的类只实现一个PropertyChanged 的Event就可以了. 例如实现一个简单的ViewModel1类: public class ViewModel1 : INotifyPropertyChanged { private string _data; public string Data { get { return _data; } set { if (_data == value) return; _data = v

[WPF系列]-数据邦定之DataTemplate 对分层数据的支持

到目前为止,我们仅讨论如何绑定和显示单个集合. 某些时候,您要绑定的集合包含其他集合. HierarchicalDataTemplate 类专用于 HeaderedItemsControl 类型以显示这样的数据. 实例演示 在下面的示例中,ListLeagueList 是 League 对象的列表. 每个 League 对象都有一个 Name 和 Division 对象的集合. 每个 Division 都有一个 Name 和 Team 对象的集合,并且每个 Team 对象都有一个 Name. <