ヒントテキストをWPFテキストボックスに追加するにはどうすればよいですか?


107

たとえば、テキストボックスが空の場合、Facebookの[検索]テキストボックスには「検索」ヒントテキストがあります。

WPFテキストボックスでこれを実現する方法?

Facebookの検索テキストボックス


2
「キューバナー」を検索してみてください。
デフォルトロケール

@MAKKAM このMSDNの記事で説明していますが、それがどのように行われるかは示していません
Louis Rhys


1
あなたが「ヒントテキスト」を求めていることを私は呼ぶつもりはありません。ヒントテキストはポップアップウィンドウです。それでも、プレースホルダーテキストを設定するときにこの質問を見つけました。そして以下の答えは私を助けました。
スティーブ・

1
ちなみにそれは透かしと呼ばれています
Blechdose '25年

回答:


158

これは、VisualBrushとのいくつかのトリガーを使用すると、はるかに簡単に実現できますStyle

<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
IsKeyboardFocusedの代わりにIsMouseCapturedを使用します。これが実際のキューバナーの反応です。
Monstieur 2012年

5
添付プロパティを使用してスタイルの再利用性を高める方法を誰かが疑問に思った場合は、stackoverflow.com
a / 650620/724944

@Kurian IsMouseCapturedは、キューをマウスでクリックしたときにのみキューを非表示にしますが、マウスボタンを離したときに再び表示されます。見た目が良くない。IsMouseOverも適切ではありません(キーボードにはフォーカスがありますが、マウスポインターが他の場所にある=>キューが表示されます)。ほとんどのキューバナーはIsKeyboardFocused(Facebookなど)を使用しており、問題ないと思います。代替の解決策は、両方のトリガーを使用することです:(IsMouseOver OR IsKeyboardFocused)
2012年

23
解決策は20要素ではなくHint = "テキストを入力してください"です。
残念ながら

8
この方法はデフォルトの条件では問題ないかもしれませんが、テキストボックスにすでに背景ブラシが含まれている場合や、フォームの背景がテキストボックスと同じ色でない場合は機能しません。
LWChris 2016年

56

これは、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>

興味深いアプローチ私はすぐには自分のことを考えなかったでしょう。
itsmatt

すてきでシンプル:)
shmulik.r

3
このソリューションは、TextBlockをIsHitTestVisible="False"
Mage Xy

1
@MageXyは最初のTextBlock(ヒント)を参照しています。
Felix

ヒントテキストをプロパティにバインドする場合は、このソリューションが適切に機能します。
PeterB 2017年

11

materialDesign HintAssistの使用についてはどうですか?私はこれを使用していますが、これもフローティングヒントを追加できます。

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

Nugetパッケージでマテリアルデザインをインストールしました。ドキュメントリンクにインストールガイドがあります。


2
非常に便利なライブラリ
AlexF11

9

コードビハインドでそれを行うには、最初にテキストの色を灰色に設定し、キーボードフォーカスを取得および喪失するためのイベントハンドラーを追加します。

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";
        }
    }
}

7
コードビハインドでそれを行う場合は-1:コントロールが乱雑になり、これが他のコントロールロジックに干渉する可能性が高くなります。
AlexeiOst


4

非常に簡単な方法で行うことができます。アイデアは、テキストボックスと同じ場所にラベルを配置することです。テキストボックスにテキストがなく、フォーカスがない場合、ラベルが表示されます。

 <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"(空の場合))。


2

別のアプローチ;-)

これはでも機能し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>

CodeBehind:

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

私が見つけた最高で最も簡単なソリューション!! ありがとう!!
スティーブ・

2

一度同じ状況になったのですが、以下の方法で解決しました。ヒントボックスの要件のみを満たしています。フォーカスなどの他のイベントにエフェクトやその他のものを追加することで、よりインタラクティブにすることができます。

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;
        }
    }


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を使用していた


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>

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、簡単に再利用可能。


-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 Designがロードされていません...次のエラーが発生します: あいまいな型参照です。「StaticExtension」という名前のタイプは、「MS.Internal.Metadata.ExposedTypes.Xaml」と「System.Windows.Markup」の少なくとも2つの名前空間で発生します。アセンブリのXmlnsDefinition属性を調整することを検討してください。 .net 3.5を使用しています


次のように変更<Trigger Property="Text" Value="{x:Static sys:String.Empty}">して問題を解決しました<Trigger Property="Text" Value="">
SUHAIL AG

6
これは別の投稿への返信のようです。質問に対する完全な解決策のみを回答として投稿してください。
ドリューゲイナー、2015年

4
@sellmeadogの答えがほぼ正しいと思われる場合は、ほとんど違いのない新しい答えを投稿するのではなく、修正することを検討してください。
0xBADF00D 2015年

-11

WPFの場合、方法はありません。あなたはそれを真似する必要があります。この例を参照してください。セカンダリ(不安定なソリューション)は、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フレームワークと呼ばれるこの実装がすでに含まれているフレームワークがあります。これはここから無料でダウンロードできます

こちらが記事です詳細について BitFlexご覧ください。Windowsエクスプローラースタイルのコントロールを探している場合、これは通常箱から出ることは決してなく、WPFはハンドルで動作しないため、Win32または既存のコントロールのような簡単なラッパーを書くことができないことがわかります。 WinFormsで。

スクリーンショット: ここに画像の説明を入力してください


1
うわー、それは少しハックに見えます。XAMLでユーザーコントロールを作成するときにこれを行うにはどうすればよいですか?
Louis Rhys、2011

あなたはしません。これがその方法です。これをカプセル化する場合は、ユーザーコントロールとCueTextプロパティを作成し、セッターでSetCueTextを呼び出します。
デビッドアンダーソン、

このアプローチを使用するには、OPがwinformsコントロールをホストする必要があると思います。または、テキストボックスのハンドルを取得する方法はありますか?
デフォルトロケール

これは、テキストボックスにフォーカスがあるかどうかなどをバインドすることによって、WPFで宣言的に実行できるもののようです。-上記の例は、WinFormsのアプローチに近く、WPFで機能しますが、正しくありません。仕方。
BrainSlugs83 2013

1
申し訳ありませんが、この答えは単に間違っています。また、すべてのリンクが壊れています。
Forest Kunecke 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.