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

前言

本文将详细介绍如何在WPF中创建一个自定义的TextBox控件,该控件不仅支持水印提示,还允许设置圆角边框。

通过本文的学习,大家将掌握如何扩展WPF控件以满足特定需求。

正文

设置水印 TextBox 控件

简单设置水印TextBox控件,废话不多说看代码:

xml 复制代码
<TextBox TextWrapping="Wrap" Margin="10" Height="69"  Visibility="Visible">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Style.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsFocused" Value="false"/>
                                    <Condition Property="Text" Value=""/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background">
                                    <Setter.Value>
                                        <VisualBrush AlignmentX="Left" AlignmentY="Top" Stretch="None">
                                            <VisualBrush.Visual>
                                                <TextBlock Padding="5 2" Background="Transparent" TextWrapping="Wrap" Height="40" Foreground="Silver">您的评价对网友有很重要的参考作用,请认真填<LineBreak/>写,谢谢合作!</TextBlock>
                                            </VisualBrush.Visual>
                                        </VisualBrush>
                                  </Setter.Value>
                              </Setter>
                         </MultiTrigger>
                    </Style.Triggers>
               </Style>
      </TextBox.Style>
</TextBox>

这里的style可以单独提出来,方便多处使用。

设置之后的效果如下:

扩展增强 TextBox

有的时候会碰到TextBox里面需要添加按钮,或者TextBox需要设置圆角。这个时候就需要添加自定义控件,添加依赖属性来扩展功能了。

1、添加自定义控件TextBoxEx

代码如下:

cs 复制代码
public class TextBoxEx : TextBox
{
    static TextBoxEx()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxEx), new FrameworkPropertyMetadata(typeof(TextBoxEx)));
    }

    public TextBoxEx()
    {
        CommandBindings.Add(new CommandBinding(SearchClickCommand, delegate
        {
            SearchClick?.Invoke(this, null);
        }));
    }

    public static RoutedUICommand SearchClickCommand = new RoutedUICommand(nameof(SearchClickCommand), nameof(SearchClickCommand), typeof(RoutedUICommand));

    public event EventHandler SearchClick;
    public string WaterMark
    {
        get { return (string)GetValue(WaterMarkProperty); }
        set { SetValue(WaterMarkProperty, value); }
    }

    public static readonly DependencyProperty WaterMarkProperty =
        DependencyProperty.Register("WaterMark", typeof(string), typeof(TextBoxEx), new PropertyMetadata(null));


    public ImageSource Icon
    {
        get { return (ImageSource)GetValue(IconProperty); }
        set { SetValue(IconProperty, value); }
    }

    public static readonly DependencyProperty IconProperty =
        DependencyProperty.Register("Icon", typeof(ImageSource), typeof(TextBoxEx), new PropertyMetadata(null));


    public new Brush BorderBrush
    {
        get { return (Brush)GetValue(BorderBrushProperty); }
        set { SetValue(BorderBrushProperty, value); }
    }

    public static readonly new DependencyProperty BorderBrushProperty =
        DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(TextBoxEx), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(234,234,234))));


    public Brush MouseOverBorderBrush
    {
        get { return (Brush)GetValue(MouseOverBorderBrushProperty); }
        set { SetValue(MouseOverBorderBrushProperty, value); }
    }

    public static readonly DependencyProperty MouseOverBorderBrushProperty =
        DependencyProperty.Register("MouseOverBorderBrush", typeof(Brush), typeof(TextBoxEx), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(79,173,216))));



    public new Brush Background
    {
        get { return (Brush)GetValue(BackgroundProperty); }
        set { SetValue(BackgroundProperty, value); }
    }

    public static readonly new DependencyProperty BackgroundProperty =
        DependencyProperty.Register("Background", typeof(Brush), typeof(TextBoxEx), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(106,103,90))));


    public Brush MouseOverBackground
    {
        get { return (Brush)GetValue(MouseOverBackgroundProperty); }
        set { SetValue(MouseOverBackgroundProperty, value); }
    }

    public static readonly DependencyProperty MouseOverBackgroundProperty =
        DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(TextBoxEx), new PropertyMetadata(Color.FromRgb(106,103,90)));


    public CornerRadius CornerRadius
    {
        get { return (CornerRadius)GetValue(CornerRadiusProperty); }
        set { SetValue(CornerRadiusProperty, value); }
    }

    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(TextBoxEx), new PropertyMetadata(new CornerRadius(0)));



    public IconDirection IconDirection
    {
        get { return (IconDirection)GetValue(IconDirectionProperty); }
        set { SetValue(IconDirectionProperty, value); }
    }

    public static readonly DependencyProperty IconDirectionProperty =
        DependencyProperty.Register("IconDirection", typeof(IconDirection), typeof(TextBoxEx), new PropertyMetadata(IconDirection.Right));


}

public enum IconDirection
{
    Left,
    Right
}

2、设置TextBoxEx样式

xml 复制代码
<Style TargetType="{x:Type local:TextBoxEx}">
    <Setter Property="Foreground" Value="#555558"/>
    <Setter Property="Background" Value="#6a675a"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TextBoxEx}">
                <Border x:Name="_border" CornerRadius="{TemplateBinding CornerRadius}" Padding="{TemplateBinding CornerRadius,Converter={StaticResource cornerRadiusToThickness} }" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition x:Name="columleft" Width="auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition x:Name="columright" Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <Image Source="{TemplateBinding Icon}"  Cursor="Hand" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="MouseLeftButtonUp">
                                    <i:InvokeCommandAction Command="local:TextBoxEx.SearchClickCommand"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </Image>
                        <ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Foreground="{TemplateBinding Foreground}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Column="1"/>
                        <TextBlock x:Name="_txtWater" IsHitTestVisible="False" Margin="3 0 0 0" VerticalAlignment="Center" Foreground="#9f9f9f"  Text="{TemplateBinding WaterMark}" Visibility="Hidden" Grid.Column="1"/>
                        <Image Source="{TemplateBinding Icon}" Cursor="Hand" Stretch="None" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="MouseLeftButtonUp">
                                    <i:InvokeCommandAction Command="local:TextBoxEx.SearchClickCommand"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </Image>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
                        <Setter TargetName="_txtWater" Property="Visibility" Value="Visible" />
                    </DataTrigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IconDirection}" Value="Left">
                        <Setter TargetName="columright" Property="Width" Value="0" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IconDirection}" Value="Right">
                        <Setter TargetName="columleft" Property="Width" Value="0" />
                    </DataTrigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="BorderBrush" Value="{Binding MouseOverBorderBrush,RelativeSource={RelativeSource TemplatedParent}}"/>
                        <Setter Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这里面使用了一个转换器cornerRadiusToThickness,转换器的作用是当TextBox设置了圆角之后,保证TextBox里的内容不溢出圆角。

WPF转换器的使用大家可以百度。

转换器的内容如下:

cs 复制代码
public class CornerRadiusToThickness : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Thickness result = new Thickness(0);
        if (value is CornerRadius)
        {
            var tem = (CornerRadius)value;
            result = new Thickness(tem.TopLeft, 0, tem.TopRight, 0);
        }
        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

另外为了触发TextBox按钮的单击事件,添加了这个两个dll文件引用,Microsoft.Expression.Interactions.dll和System.Windows.Interactivity.dll。

在顶部定义 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

3、引用方法

xml 复制代码
<local:TextBoxEx WaterMark="请输入搜索内容..." SearchClick="TextBoxEx_SearchClick" KeyDown="TextBoxEx_KeyDown" Background="#dfe1e3" VerticalAlignment="Center" MouseOverBackground="#dfe1e3" CornerRadius="13.5" IconDirection="Right" Icon="/Images/Title/search.png" Height="25" />

项目源码

GitHub:github.com/cmfGit/WpfD...

关键词

WPF、自定义控件、TextBox、水印提示、圆角边框、用户体验、控件开发、附加属性、样式模板

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:一叶知秋,知寒冬

出处:cnblogs.com/pumbaa/p/14736311.html

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

相关推荐
争不过朝夕,又念着往昔1 小时前
Go语言反射机制详解
开发语言·后端·golang
绝无仅有2 小时前
企微审批对接错误与解决方案
后端·算法·架构
Super Rookie3 小时前
Spring Boot 企业项目技术选型
java·spring boot·后端
来自宇宙的曹先生3 小时前
用 Spring Boot + Redis 实现哔哩哔哩弹幕系统(上篇博客改进版)
spring boot·redis·后端
expect7g3 小时前
Flink-Checkpoint-1.源码流程
后端·flink
00后程序员3 小时前
Fiddler中文版如何提升API调试效率:本地化优势与开发者实战体验汇总
后端
开开心心_Every3 小时前
全能视频处理工具介绍说明
开发语言·人工智能·django·pdf·flask·c#·音视频
86Eric3 小时前
C# 入门学习教程(二)
c#·操作符·语句
用户8122199367224 小时前
C# .Net Core零基础从入门到精通实战教程全集【190课】
后端
bobz9654 小时前
FROM scratch: docker 构建方式分析
后端