如何向WPF文本框添加提示文本?

时间:2011-09-15 03:41:56

标签: .net wpf user-interface textbox

例如,当文本框为空时,Facebook在“搜索”文本框中有一个“搜索”提示文本。

如何使用WPF文本框实现这一点?

Facebook's search textbox

14 个答案:

答案 0 :(得分:151)

使用VisualBrushStyle中的一些触发器,您可以更轻松地完成此任务:

<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <Style.Resources>
                <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                    <VisualBrush.Visual>
                        <Label Content="Search" Foreground="LightGray" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Style.Resources>
            <Style.Triggers>
                <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="Text" Value="{x:Null}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter Property="Background" Value="White" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

为了增加此Style的可重用性,您还可以创建一组附加属性来控制实际的提示横幅文本,颜色,方向等。

答案 1 :(得分:47)

这是我的简单解决方案,改编自Microsoft(https://code.msdn.microsoft.com/windowsapps/How-to-add-a-hint-text-to-ed66a3c6

    <Grid Background="White" HorizontalAlignment="Right" VerticalAlignment="Top"  >
        <!-- overlay with hint text -->
        <TextBlock Margin="5,2" MinWidth="50" Text="Suche..." 
                   Foreground="LightSteelBlue" Visibility="{Binding ElementName=txtSearchBox, Path=Text.IsEmpty, Converter={StaticResource MyBoolToVisibilityConverter}}" />
        <!-- enter term here -->
        <TextBox MinWidth="50" Name="txtSearchBox" Background="Transparent" />
    </Grid>

答案 2 :(得分:10)

通过将文本颜色最初设置为灰色并添加事件处理程序以获得和失去键盘焦点,在代码隐藏中执行此操作。

TextBox tb = new TextBox();
tb.Foreground = Brushes.Gray;
tb.Text = "Text";
tb.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_GotKeyboardFocus);
tb.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_LostKeyboardFocus);

然后是事件处理程序:

private void tb_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    if(sender is TextBox)
    {
        //If nothing has been entered yet.
        if(((TextBox)sender).Foreground == Brushes.Gray)
        {
            ((TextBox)sender).Text = "";
            ((TextBox)sender).Foreground = Brushes.Black;
        }
    }
}


private void tb_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    //Make sure sender is the correct Control.
    if(sender is TextBox)
    {
        //If nothing was entered, reset default text.
        if(((TextBox)sender).Text.Trim().Equals(""))
        {
            ((TextBox)sender).Foreground = Brushes.Gray;
            ((TextBox)sender).Text = "Text";
        }
    }
}

答案 3 :(得分:5)

您必须通过继承文本框来创建自定义控件。 下面的链接有一个关于搜索文本框示例的极好示例。 请看看这个

http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/

答案 4 :(得分:3)

你可以用一种非常简单的方式做。  我们的想法是将Label放在与文本框相同的位置。如果文本框没有文本且没有焦点,则您的标签将可见。

 <Label Name="PalceHolder"  HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40" VerticalAlignment="Top" Width="239" FontStyle="Italic"  Foreground="BurlyWood">PlaceHolder Text Here
  <Label.Style>
    <Style TargetType="{x:Type Label}">
      <Setter Property="Visibility" Value="Hidden"/>
      <Style.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding ="{Binding ElementName=PalceHolder, Path=Text.Length}" Value="0"/>
            <Condition Binding ="{Binding ElementName=PalceHolder, Path=IsFocused}" Value="False"/>
          </MultiDataTrigger.Conditions>
          <Setter Property="Visibility" Value="Visible"/>
        </MultiDataTrigger>
      </Style.Triggers>
    </Style>
  </Label.Style>
</Label>
<TextBox  Background="Transparent" Name="TextBox1" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40"TextWrapping="Wrap" Text="{Binding InputText,Mode=TwoWay}" VerticalAlignment="Top" Width="239" />

奖励:如果你想拥有textBox的默认值,请务必在提交数据后设置它(例如:“InputText”=“PlaceHolder Text Here”,如果为空)。

答案 5 :(得分:1)

另一种方法;-)

这也适用于PasswordBox。如果您想将其与TextBox一起使用,只需与PasswordChanged交换TextChanged

<强> XAML:

<Grid>
    <!-- overlay with hint text -->
    <TextBlock Margin="5,2"
                Text="Password"
                Foreground="Gray"
                Name="txtHintPassword"/>
    <!-- enter user here -->
    <PasswordBox Name="txtPassword"
                Background="Transparent"
                PasswordChanged="txtPassword_PasswordChanged"/>
</Grid>

<强>代码隐藏:

private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
{
    txtHintPassword.Visibility = Visibility.Visible;
    if (txtPassword.Password.Length > 0)
    {
        txtHintPassword.Visibility = Visibility.Hidden;
    }
}

答案 6 :(得分:1)

我曾经遇到过同样的情况,我按照以下方式解决了这个问题。 我只满足了提示框的要求,你可以通过在焦点等其他事件上添加效果和其他东西来使其更具互动性。

WPF代码(我删除了样式以使其可读)

<Grid Margin="0,0,0,0"  Background="White">
    <Label Name="adminEmailHint" Foreground="LightGray" Padding="6"  FontSize="14">Admin Email</Label>
    <TextBox Padding="4,7,4,8" Background="Transparent" TextChanged="adminEmail_TextChanged" Height="31" x:Name="adminEmail" Width="180" />
</Grid>
<Grid Margin="10,0,10,0" Background="White" >
    <Label Name="adminPasswordHint" Foreground="LightGray" Padding="6"  FontSize="14">Admin Password</Label>
    <PasswordBox Padding="4,6,4,8" Background="Transparent" PasswordChanged="adminPassword_PasswordChanged" Height="31" x:Name="adminPassword" VerticalContentAlignment="Center" VerticalAlignment="Center" Width="180" FontFamily="Helvetica" FontWeight="Light" FontSize="14" Controls:TextBoxHelper.Watermark="Admin Password"  FontStyle="Normal" />
</Grid>

C#代码

private void adminEmail_TextChanged(object sender, TextChangedEventArgs e)
    {
        if(adminEmail.Text.Length == 0)
        {
            adminEmailHint.Visibility = Visibility.Visible;
        }
        else
        {
            adminEmailHint.Visibility = Visibility.Hidden;
        }
    }

private void adminPassword_PasswordChanged(object sender, RoutedEventArgs e)
    {
        if (adminPassword.Password.Length == 0)
        {
            adminPasswordHint.Visibility = Visibility.Visible;
        }
        else
        {
            adminPasswordHint.Visibility = Visibility.Hidden;
        }
    }

答案 7 :(得分:0)

我使用了丢失的焦点事件:

Private Sub txtSearchBox_GotFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles txtSearchBox.GotFocus
    If txtSearchBox.Text = "Search" Then
        txtSearchBox.Text = ""
    Else

    End If

End Sub

Private Sub txtSearchBox_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles txtSearchBox.LostFocus
    If txtSearchBox.Text = "" Then
        txtSearchBox.Text = "Search"
    Else

    End If
End Sub

效果很好,但文字仍然是灰色的。需要清理。我使用的是VB.NET

答案 8 :(得分:0)

  <Grid>
    <TextBox Name="myTextBox"/>
    <TextBlock>
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=myTextBox, Path=Text.IsEmpty}" Value="True">
                        <Setter Property="Text" Value="Prompt..."/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</Grid>

答案 9 :(得分:0)

另一种解决方案是使用像MahApps.Metro这样的WPF工具包。它有许多不错的功能,如文本框水印:

Controls:TextBoxHelper.Watermark="Search..."

请参阅http://mahapps.com/controls/textbox.html

答案 10 :(得分:0)

如何使用materialDesign HintAssist?我正在使用它,您也可以添加浮动提示:

<TextBox Width="150" Height="40" Text="hello" materialDesign:HintAssist.Hint="address"  materialDesign:HintAssist.IsFloating="True"></TextBox>

我使用Nuget软件包安装了Material Design,documentation链接中有安装指南

答案 11 :(得分:0)

这是我的看法:

<ControlTemplate>
    <Grid>
        <Grid.Resources>
            <!--Define look / layout for both TextBoxes here. I applied custom Padding and BorderThickness for my application-->
            <Style TargetType="TextBox">
                <Setter Property="Padding" Value="4"/>
                <Setter Property="BorderThickness" Value="2"/>
            </Style>
        </Grid.Resources>

        <TextBox x:Name="TbSearch"/>
        <TextBox x:Name="TbHint" Text="Suche" Foreground="LightGray"
                 Visibility="Hidden" IsHitTestVisible="False" Focusable="False"/>
    </Grid>

    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition SourceName="TbSearch" Property="Text" Value="{x:Static sys:String.Empty}"/>
                <Condition SourceName="TbSearch" Property="IsKeyboardFocused" Value="False"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter TargetName="TbHint" Property="Visibility" Value="Visible"/>
            </MultiTrigger.Setters>
        </MultiTrigger>

        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition SourceName="TbSearch" Property="Text" Value="{x:Null}"/>
                <Condition SourceName="TbSearch" Property="IsKeyboardFocused" Value="False"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter TargetName="TbHint" Property="Visibility" Value="Visible"/>
            </MultiTrigger.Setters>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

我认为包括最高答案在内的大多数其他答案都有缺陷。

此解决方案在所有情况下均适用。纯XAML,易于重用。

答案 12 :(得分:-1)

我使用VisualBrush以及Style建议的sellmeadog中的一些触发器完成此操作。

<TextBox>
        <TextBox.Style>
            <Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
                <Style.Resources>
                    <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                        <VisualBrush.Visual>
                            <Label Content="Search" Foreground="LightGray" />
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Style.Resources>
                <Style.Triggers>
                    <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                        <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                    </Trigger>
                    <Trigger Property="Text" Value="{x:Null}">
                        <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

@sellmeadog:应用程序正在运行,bt设计未加载......出现以下错误: 不明确的类型参考。名为“StaticExtension”的类型出现在至少两个名称空间中,“MS.Internal.Metadata.ExposedTypes.Xaml”和“System.Windows.Markup”。考虑调整程序集XmlnsDefinition属性。 我正在使用.net 3.5

答案 13 :(得分:-10)

对于WPF,没有办法。你必须模仿它。 See this example。辅助(片状解决方案)是托管从TextBox继承的WinForms用户控件,并将EM_SETCUEBANNER消息发送到编辑控件。即

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam);

private const Int32 ECM_FIRST = 0x1500;
private const Int32 EM_SETCUEBANNER = ECM_FIRST + 1;

private void SetCueText(IntPtr handle, string cueText) {
    SendMessage(handle, EM_SETCUEBANNER, IntPtr.Zero, Marshal.StringToBSTR(cueText));
}

public string CueText {
    get {
        return m_CueText;
    } 
    set {
        m_CueText = value;
        SetCueText(this.Handle, m_CueText);
}

另外,如果你想托管一个WinForm控件方法,我有一个框架已经包含了这个名为BitFlex Framework的实现,你可以download for free here

如果您想了解更多信息,请关于BitFlex

Here is an article。您将开始发现,如果您希望使用Windows资源管理器样式控件,这通常永远不会开箱即用,并且因为WPF通常不能使用句柄,您不能在Win32或现有控件周围编写简单的包装器,就像您可以使用WinForms。

截图: enter image description here