WPF自定义控件那些事(二)

自定义文本

先看效果图:
图片
       自定义文本框实现功能:设置上、下、左、右、背景提示文本。在网上能找到很多例子,但很多都是有问题的,比如输入字符长度超过文本框所能显示的长度时,不能自动滚动等。

      ZbTextBox.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Zbsoft.WpfControls
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Zbsoft.WpfControls"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Zbsoft.WpfControls;assembly=Zbsoft.WpfControls"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:CustomControl1/>
    ///
    /// </summary>
    public class ZbTextBox : TextBox
    {
        static ZbTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ZbTextBox), new FrameworkPropertyMetadata(typeof(ZbTextBox)));
           
            BackPromptStringProperty = DependencyProperty.Register("BackPromptString",
                typeof(string), typeof(ZbTextBox));
            LeftPromptStringProperty = DependencyProperty.Register("LeftPromptString",
                typeof(string), typeof(ZbTextBox), new PropertyMetadata("", new PropertyChangedCallback(OnPromptValueChanged)));
            TopPromptStringProperty = DependencyProperty.Register("TopPromptString",
                typeof(string), typeof(ZbTextBox), new PropertyMetadata("", new PropertyChangedCallback(OnPromptValueChanged)));
            RightPromptStringProperty = DependencyProperty.Register("RightPromptString",
                typeof(string), typeof(ZbTextBox), new PropertyMetadata("", new PropertyChangedCallback(OnPromptValueChanged)));
            BottomPromptStringProperty = DependencyProperty.Register("BottomPromptString",
                typeof(string), typeof(ZbTextBox), new PropertyMetadata("", new PropertyChangedCallback(OnPromptValueChanged)));
            LeftPromptMarginProperty = DependencyProperty.Register("LeftPromptMargin",
                typeof(Thickness), typeof(ZbTextBox));
            TopPromptMarginProperty = DependencyProperty.Register("TopPromptMargin",
                typeof(Thickness), typeof(ZbTextBox));
            RightPromptMarginProperty = DependencyProperty.Register("RightPromptMargin",
                typeof(Thickness), typeof(ZbTextBox));
            BottomPromptMarginProperty = DependencyProperty.Register("BottomPromptMargin",
                typeof(Thickness), typeof(ZbTextBox));
            CornerRadiusProperty = DependencyProperty.Register("CornerRadius",
                typeof(CornerRadius), typeof(ZbTextBox));
            TopPromptHeightProperty = DependencyProperty.Register("TopPromptHeight",
                typeof(GridLength), typeof(ZbTextBox));
            LeftPromptWidthProperty = DependencyProperty.Register("LeftPromptWidth",
                typeof(GridLength), typeof(ZbTextBox));
            RightPromptWidthProperty = DependencyProperty.Register("RightPromptWidth",
                typeof(GridLength), typeof(ZbTextBox));
            BottomPromptHeightProperty = DependencyProperty.Register("BottomPromptHeight",
                typeof(GridLength), typeof(ZbTextBox));
            PromptForegroundProperty = DependencyProperty.Register("PromptForeground",
                typeof(Brush), typeof(ZbTextBox));
        }
        #region 左、上、右、下、背景提示文本属性
        public static DependencyProperty PromptForegroundProperty;
        /// <summary>
        /// 提示文本前景色
        /// </summary>
        public Brush PromptForeground
        {
            get { return (Brush)GetValue(PromptForegroundProperty); }
            set { SetValue(PromptForegroundProperty, value); }
        }
        public static DependencyProperty BackPromptStringProperty;
        /// <summary>
        /// 背景提示文本
        /// </summary>
        public string BackPromptString
        {
            get { return (string)GetValue(BackPromptStringProperty); }
            set { SetValue(BackPromptStringProperty, value); }
        }
        public static DependencyProperty LeftPromptStringProperty;
        /// <summary>
        /// 左侧前导文本
        /// </summary>
        public string LeftPromptString
        {
            get { return (string)GetValue(LeftPromptStringProperty); }
            set { SetValue(LeftPromptStringProperty, value); }
        }
        public static DependencyProperty TopPromptStringProperty;
        /// <summary>
        /// 上方提示文本
        /// </summary>
        public string TopPromptString
        {
            get { return (string)GetValue(TopPromptStringProperty); }
            set { SetValue(TopPromptStringProperty, value); }
        }
        public static DependencyProperty RightPromptStringProperty;
        /// <summary>
        /// 右侧提示文本
        /// </summary>
        public string RightPromptString
        {
            get { return (string)GetValue(RightPromptStringProperty); }
            set { SetValue(RightPromptStringProperty, value); }
        }
        public static DependencyProperty BottomPromptStringProperty;
        /// <summary>
        /// 下方提示文本
        /// </summary>
        public string BottomPromptString
        {
            get { return (string)GetValue(BottomPromptStringProperty); }
            set { SetValue(BottomPromptStringProperty, value);}
        }
        public static DependencyProperty LeftPromptMarginProperty;
        /// <summary>
        /// 左侧文本边界
        /// </summary>
        public Thickness LeftPromptMargin
        {
            get { return (Thickness)GetValue(LeftPromptMarginProperty); }
            set { SetValue(LeftPromptMarginProperty, value); }
        }
        public static DependencyProperty TopPromptMarginProperty;
        /// <summary>
        /// 上方文本边界
        /// </summary>
        public Thickness TopPromptMargin
        {
            get { return (Thickness)GetValue(TopPromptMarginProperty); }
            set { SetValue(TopPromptMarginProperty, value); }
        }
        public static DependencyProperty RightPromptMarginProperty;
        /// <summary>
        /// 右侧文本边界
        /// </summary>
        public Thickness RightPromptMargin
        {
            get { return (Thickness)GetValue(RightPromptMarginProperty); }
            set { SetValue(RightPromptMarginProperty, value); }
        }
        public static DependencyProperty BottomPromptMarginProperty;
        /// <summary>
        /// 下方文本边界
        /// </summary>
        public Thickness BottomPromptMargin
        {
            get { return (Thickness)GetValue(BottomPromptMarginProperty); }
            set { SetValue(BottomPromptMarginProperty, value); }
        }
        public static DependencyProperty TopPromptHeightProperty;
        /// <summary>
        /// 上方文本高度,一般不用设置,自动
        /// </summary>
        public GridLength TopPromptHeight
        {
            get { return (GridLength)GetValue(TopPromptHeightProperty); }
            set { SetValue(TopPromptHeightProperty, value); }
        }
        public static DependencyProperty LeftPromptWidthProperty;
        /// <summary>
        /// 左侧文本宽度,一般不用设置,自动
        /// </summary>
        public GridLength LeftPromptWidth
        {
            get { return (GridLength)GetValue(LeftPromptWidthProperty); }
            set { SetValue(LeftPromptWidthProperty, value); }
        }
        public static DependencyProperty RightPromptWidthProperty;
        /// <summary>
        /// 右侧文本宽度,一般不用设置,自动
        /// </summary>
        public GridLength RightPromptWidth
        {
            get { return (GridLength)GetValue(RightPromptWidthProperty); }
            set { SetValue(RightPromptWidthProperty, value); }
        }
        public static DependencyProperty BottomPromptHeightProperty;
        /// <summary>
        /// 下方文本高度,一般不用设置,自动
        /// </summary>
        public GridLength BottomPromptHeight
        {
            get { return (GridLength)GetValue(BottomPromptHeightProperty); }
            set { SetValue(BottomPromptHeightProperty, value); }
        }
        #endregion  左、上、右、下、背景提示文本属性

        public static DependencyProperty CornerRadiusProperty;
        /// <summary>
        /// 边框弧度
        /// </summary>
        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }
        /// <summary>
        /// 左、上、下、右边文本变化时,自动调整对应宽度和高度
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnPromptValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DependencyProperty p = null;
            switch (e.Property.Name)
            {
                case "LeftPromptString":
                    p = LeftPromptWidthProperty;
                    break;
                case "TopPromptString":
                    p = TopPromptHeightProperty;
                    break;
                case "BottomPromptString":
                    p = BottomPromptHeightProperty;
                    break;
                case "RightPromptString":
                    p = RightPromptWidthProperty;
                    break;
            }
            if (string.IsNullOrEmpty((string)e.NewValue))
                d.SetValue(p, new GridLength(0));
            else
                if (((GridLength)(d.GetValue(p))).Value <= 1)
                    d.SetValue(p, new GridLength(0, GridUnitType.Auto));
        }
    }
}
ZbTextBox.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Zbsoft.WpfControls">
<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="/Zbsoft.WpfControls;component/Resources/ZbShared.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<!--自定义文本框样式-->
<Style TargetType="{x:Type local:ZbTextBox}">
  <Setter Property="SnapsToDevicePixels"
    Value="True" />
  <Setter Property="CornerRadius"
      Value="{StaticResource TextBoxBorderCornerRadius}"></Setter>
  <Setter Property="BorderThickness"
      Value="{StaticResource TextBoxBorderThickness}"></Setter>
  <Setter Property="Padding"
      Value="{StaticResource TextBoxPadding}"></Setter>
  <Setter Property="TopPromptHeight"
      Value="0"></Setter>
  <Setter Property="LeftPromptWidth"
      Value="0"></Setter>
  <Setter Property="LeftPromptMargin"
    Value="0,0,2,0"></Setter>
  <Setter Property="RightPromptWidth"
      Value="0"></Setter>
  <Setter Property="BottomPromptHeight"
      Value="0"></Setter>
   <Setter Property="BorderThickness"
      Value="{StaticResource TextBoxBorderThickness}"></Setter>
  <Setter Property="Padding"
      Value="{StaticResource TextBoxPadding}"></Setter>
  <Setter Property="BorderBrush"
      Value="{StaticResource TextBoxBorderDefaultBrush}"></Setter>
  <Setter Property="Foreground"
      Value="{StaticResource TextBoxForeground}"></Setter>
  <Setter Property="Background"
    Value="{StaticResource TextBoxBackground}"></Setter>
  <Setter Property="PromptForeground"
      Value="{StaticResource TextBoxPromptForeground}"></Setter>
  <Setter Property="KeyboardNavigation.TabNavigation"
      Value="None" />
  <Setter Property="FocusVisualStyle"
      Value="{x:Null}" />
  <Setter Property="Template">
   <Setter.Value>
    <ControlTemplate TargetType="{x:Type local:ZbTextBox}">
     <Grid Name="LayoutGrid">
      <Grid.RowDefinitions>
       <RowDefinition Height="{TemplateBinding local:ZbTextBox.TopPromptHeight}"></RowDefinition>
       <RowDefinition></RowDefinition>
       <RowDefinition Height="{TemplateBinding local:ZbTextBox.BottomPromptHeight}"></RowDefinition>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
       <ColumnDefinition Width="{TemplateBinding local:ZbTextBox.LeftPromptWidth}"></ColumnDefinition>
       <ColumnDefinition></ColumnDefinition>
       <ColumnDefinition Width="{TemplateBinding local:ZbTextBox.RightPromptWidth}"></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <!--左侧文本-->
      <TextBlock x:Name="PART_LeftPromptTextBlock"
            Foreground="{TemplateBinding local:ZbTextBox.PromptForeground}"
            Grid.Row="1"
            VerticalAlignment="Center"
            HorizontalAlignment="Right"
            Text="{TemplateBinding local:ZbTextBox.LeftPromptString}"
            Margin="{TemplateBinding local:ZbTextBox.LeftPromptMargin}"></TextBlock>
      <!--上方文本-->
      <TextBlock x:Name="PART_TopPromptTextBlock"
            Foreground="{TemplateBinding local:ZbTextBox.PromptForeground}"
            Grid.Column="1"
            Text="{TemplateBinding local:ZbTextBox.TopPromptString}"
            Margin="{TemplateBinding local:ZbTextBox.TopPromptMargin}"></TextBlock>
      <!--右侧文本-->
      <TextBlock x:Name="PART_RightPromptTextBlock"
            Foreground="{TemplateBinding local:ZbTextBox.PromptForeground}"
            Grid.Column="2"
            VerticalAlignment="Center"
            Grid.Row="1"
            Text="{TemplateBinding local:ZbTextBox.RightPromptString}"
            Margin="{TemplateBinding local:ZbTextBox.RightPromptMargin}"></TextBlock>
      <!--下方文本-->
      <TextBlock x:Name="PART_BottomPromptTextBlock"
            Foreground="{TemplateBinding local:ZbTextBox.PromptForeground}"
            Grid.Column="1"
            Grid.Row="2"
            Text="{TemplateBinding local:ZbTextBox.BottomPromptString}"
            Margin="{TemplateBinding local:ZbTextBox.BottomPromptMargin}"></TextBlock>
      <!--文本框布局-->
      <Grid Grid.Column="1"
         Grid.Row="1">
       <!--边框-->
       <Border x:Name="Bd"
           BorderThickness="{TemplateBinding local:ZbTextBox.BorderThickness}"
           BorderBrush="{TemplateBinding local:ZbTextBox.BorderBrush}"
           CornerRadius="{TemplateBinding local:ZbTextBox.CornerRadius}"
         Background="{TemplateBinding local:ZbTextBox.Background}">
        <!--文本框容器宿主-->
        <ScrollViewer Name="PART_ContentHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
               SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}">
        </ScrollViewer>
       </Border>
       <!--背景文本框,斜体、部分透明-->
       <TextBlock FontStyle="Italic"
            Opacity="0.67"
            VerticalAlignment="Center"
            x:Name="PART_BackPromptTextBlock"
            Visibility="Hidden"
            Text="{TemplateBinding local:ZbTextBox.BackPromptString}"
            Margin="{TemplateBinding local:ZbTextBox.Padding}"></TextBlock>
      </Grid>
     </Grid>
     <ControlTemplate.Triggers>
      <!--文本框为空值时,显示背景文本-->
      <DataTrigger Binding="{Binding Path=Text.Length, RelativeSource={RelativeSource Mode=Self}}"
          Value="0">
       <Setter TargetName="PART_BackPromptTextBlock"
         Property="Visibility"
         Value="Visible" />
      </DataTrigger>
       <!--鼠标进入时-->
      <Trigger Property="IsMouseOver"
           Value="True">
       <Setter TargetName="Bd"
           Property="BorderBrush"
           Value="{StaticResource TextBoxBorderMouseOverBrush}"></Setter>
      </Trigger>
      <!--获得焦点时,设置左侧、上方文本为阴影效果-->
       <Trigger Property="IsFocused"
           Value="True">
       <Setter TargetName="Bd"
           Property="BorderBrush"
           Value="{StaticResource TextBoxBorderFocusedBrush}"></Setter>
       <Setter TargetName="Bd"
           Property="BorderThickness"
           Value="{StaticResource TextBoxBorderFocusedThickness}"></Setter>
      </Trigger>
       <!--文本框禁用时,设置文本框的前景与背景画刷-->
      <Trigger Property="IsEnabled"
           Value="false">
       <Setter TargetName="Bd"
           Property="Background"
           Value="{StaticResource TextBoxBorderDisabledBackBrush}" />
       <Setter Property="Foreground"
           Value="{StaticResource TextBoxDisabledForeground}"></Setter>
       <Setter Property="BorderBrush" TargetName="Bd"
           Value="{StaticResource TextBoxBorderDisabledBrush}" />
      </Trigger>
     </ControlTemplate.Triggers>
    </ControlTemplate>
   </Setter.Value>
  </Setter>
</Style>
</ResourceDictionary>

测试见前一讲。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值