WPF文本框实现placeholder输入提示的两种方法

WPF文本框实现placeholder效果

在WPF中,我们可以通过以下两种方式实现文本框的placeholder效果:

1. 使用Watermark

在WPF中,我们可以使用Watermark来实现文本框的placeholder效果。Watermark是一种帮助用户更好地理解文本框的提示信息,同时不会对用户的输入造成干扰的一种视觉效果。我们可以使用以下代码来实现Watermark:

<TextBox Text="{Binding Text, Mode=TwoWay}"
         xmlns:local="clr-namespace:MyNamespace"
         local:WatermarkService.Watermark="请输入文本"
         local:WatermarkService.IsWatermarkEnabled="True" />

其中,"请输入文本"是我们要显示的placeholder文本,WatermarkService是我们自定义的一个附加属性类,用来实现Watermark效果。

以下是WatermarkService的代码:

public class WatermarkService : DependencyObject
{
    public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
        "Watermark",
        typeof(string),
        typeof(WatermarkService),
        new FrameworkPropertyMetadata(string.Empty));

    public static readonly DependencyProperty IsWatermarkEnabledProperty = DependencyProperty.RegisterAttached(
        "IsWatermarkEnabled",
        typeof(bool),
        typeof(WatermarkService),
        new FrameworkPropertyMetadata(false, IsWatermarkEnabledChanged));

    public static string GetWatermark(DependencyObject obj)
    {
        return (string)obj.GetValue(WatermarkProperty);
    }

    public static void SetWatermark(DependencyObject obj, string value)
    {
        obj.SetValue(WatermarkProperty, value);
    }

    public static bool GetIsWatermarkEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsWatermarkEnabledProperty);
    }

    public static void SetIsWatermarkEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsWatermarkEnabledProperty, value);
    }

    private static void IsWatermarkEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = d as TextBox;
        if (textBox == null)
        {
            return;
        }

        if ((bool)e.NewValue)
        {
            textBox.GotFocus += TextBox_GotFocus;
            textBox.LostFocus += TextBox_LostFocus;
            UpdateWatermark(textBox);
        }
        else
        {
            textBox.GotFocus -= TextBox_GotFocus;
            textBox.LostFocus -= TextBox_LostFocus;
            RemoveWatermark(textBox);
        }
    }

    private static void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        var textBox = sender as TextBox;
        if (textBox == null)
        {
            return;
        }

        RemoveWatermark(textBox);
    }

    private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        var textBox = sender as TextBox;
        if (textBox == null)
        {
            return;
        }

        UpdateWatermark(textBox);
    }

    private static void UpdateWatermark(TextBox textBox)
    {
        if (string.IsNullOrEmpty(textBox.Text))
        {
            textBox.Tag = textBox.Background;
            textBox.Background = Brushes.Transparent;
            textBox.Text = GetWatermark(textBox);
        }
    }

    private static void RemoveWatermark(TextBox textBox)
    {
        if (textBox.Text == GetWatermark(textBox))
        {
            textBox.Text = string.Empty;
            textBox.Background = (Brush)textBox.Tag;
        }
    }
}

2. 使用Style

我们也可以通过Style来实现文本框的placeholder效果。以下是实现方式:

<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="Padding" Value="2" />
    <Setter Property="AllowDrop" Value="true" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid>
                    <Border x:Name="border"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="true" />
                    <ScrollViewer x:Name="PART_ContentHost"
                                  Focusable="false"
                                  HorizontalScrollBarVisibility="Hidden"
                                  VerticalScrollBarVisibility="Hidden" />
                    <TextBlock x:Name="PART_Watermark"
                               Text="{Binding Path=(local:WatermarkService.Watermark), RelativeSource={RelativeSource TemplatedParent}}"
                               Foreground="Gray"
                               Visibility="Collapsed"
                               IsHitTestVisible="false"
                               Margin="{TemplateBinding Padding}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                        <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                        <Setter TargetName="PART_Watermark" Property="Visibility" Value="Visible" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="true">
                        <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
                        <Setter TargetName="PART_Watermark" Property="Visibility" Value="Collapsed" />
                    </Trigger>
                    <Trigger Property="Text" Value="">
                        <Setter TargetName="PART_Watermark" Property="Visibility" Value="Visible" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

以上是两种实现方式的代码,你可以根据你的实际需求选择其中一种。希望本文对你有所帮助!

猜你喜欢

转载自blog.csdn.net/Documentlv/article/details/130290564
今日推荐