WPF 텍스트 상자에 힌트 텍스트를 추가하려면 어떻게해야합니까?


107

예를 들어 Facebook은 텍스트 상자가 비어있을 때 검색 텍스트 상자에 "검색"힌트 텍스트가 있습니다.

WPF 텍스트 상자로 이것을 달성하는 방법 ??

Facebook의 검색 텍스트 상자


2
"큐 배너"를 검색해보십시오.
기본 로케일

@MAKKAM 이 MSDN 기사 그것은하지만 어떻게하는지 보여주지 않는다 나와
루이의 Rhys


1
나는 당신이 '힌트 텍스트'를 요구하는 것을 부르지 않을 것입니다. 나에게 힌트 텍스트는 팝업 창입니다. 그럼에도 불구하고 자리 표시 자 텍스트를 설정하고 싶을 때이 질문을 발견했습니다. 아래 답변이 도움이되었습니다.
스티브

1
그건 그렇고 워터 마크라고합니다
Blechdose

답변:


158

a 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>

this의 재사용 성을 높이기 위해 Style실제 큐 배너 텍스트, 색상, 방향 등을 제어하는 ​​연결된 속성 집합을 만들 수도 있습니다.


1
IsKeyboardFocused 대신 IsMouseCaptured를 사용하십시오. 이것이 실제 큐 배너가 반응하는 방식입니다.
Monstieur

5
스타일 재사용 성을 높이기 위해 연결된 속성을 사용하는 방법에 대해 궁금한 사람이 있으면 다음을 참조하십시오. stackoverflow.com/a/650620/724944
surfen

@Kurian IsMouseCaptured는 마우스로 클릭 할 때만 큐를 사라지게하지만 마우스 버튼을 놓으면 다시 나타납니다. 보기 좋지 않습니다. IsMouseOver도 좋지 않습니다 (키보드에 포커스가 있지만 마우스 포인터가 다른 곳에 있음 => 큐가 표시됨). 대부분의 큐 배너는 IsKeyboardFocused (예 : Facebook)를 사용하며 괜찮다고 생각합니다. 대체 솔루션은 두 트리거를 모두 사용하는 것입니다. (IsMouseOver 또는 IsKeyboardFocused)
surfen

23
해결책은 20 개의 요소가 아닌 Hint = "Please enter your text"여야합니다 ... 아아, 이것은 전설적인 내장 텍스트 상자에서 지원되지 않습니다 ...
Mzn

8
이 방법은 기본 조건에 적합 할 수 있지만 텍스트 상자에 이미 배경 브러시가 포함되어 있거나 양식 배경이 텍스트 상자와 같은 색상이 아닌 경우에는 작동하지 않습니다.
LWChris

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 2015-06-18

좋은 간단한 :)
shmulik.r

3
이 솔루션은 TextBlock을IsHitTestVisible="False"
Mage Xy

1
@MageXy는 첫 번째 TextBlock (힌트 하나)을 참조합니다.
Felix

이 솔루션은 힌트 텍스트를 속성에 바인딩하려는 경우 유용합니다.
PeterB

11

materialDesign HintAssist 를 사용 하는 것은 어떻습니까? 나는 이것을 사용하고 있습니다. 또한 부동 힌트를 추가 할 수 있습니다.

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

Nuget Package로 Material Design을 설치했습니다. 문서 링크에 설치 가이드가 있습니다.


2
매우 유용한 라이브러리
AlexF11 2010 년

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

내가 찾은 최고의 가장 간단한 솔루션 !! 감사!!
steve

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

1

또 다른 해결책은 MahApps.Metro와 같은 WPF 도구 키트를 사용하는 것입니다. 텍스트 상자 워터 마크와 같은 많은 멋진 기능이 있습니다.

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

http://mahapps.com/controls/textbox.html 참조


0

나는 got 및 lost focus 이벤트를 사용했습니다.

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

나는 a 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를 사용하고 있습니다.


변경하여 문제를 해결 <Trigger Property="Text" Value="{x:Static sys:String.Empty}"><Trigger Property="Text" Value="">
하일 AG

6
다른 게시물에 대한 응답 인 것 같습니다. 질문에 대한 완전한 해결책 만 답변으로 게시하십시오.
Drew Gaynor

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 Framework라는이 구현이 이미 포함 된 프레임 워크가 있습니다 . 여기에서 무료로 다운로드 할 수 있습니다 .

다음은 기사입니다 좀 더 자세한 정보를 원하는 경우 BitFlex에 대한이. Windows 탐색기 스타일 컨트롤을 사용하려는 경우 일반적으로 기본적으로 제공되지 않으며 WPF가 일반적으로 핸들과 함께 작동하지 않기 때문에 Win32 또는 기존 컨트롤에 대한 쉬운 래퍼를 작성할 수 없다는 사실을 알게 될 것입니다. WinForms와 함께.

스크린 샷 : 여기에 이미지 설명 입력


1
와우, 약간 엉망인 것 같습니다 .. XAML로 사용자 정의 컨트롤을 만들 때 어떻게이 작업을 수행 할 수 있습니까?
Louis Rhys 2011 년

당신은하지 않습니다. 이것이 수행되는 방법입니다. 이것을 캡슐화하려면 사용자 컨트롤과 CueText 속성을 만들고 setter에서 SetCueText를 호출하십시오.
데이비드 앤더슨

이 접근 방식을 사용하려면 OP가 winforms 컨트롤을 호스팅해야한다고 생각합니다. 아니면 텍스트 상자 핸들을 얻는 방법이 있습니까?
기본 로케일

이것은 텍스트 상자에 포커스가 있는지 여부 등에 대한 바인딩을 통해 WPF로 선언적으로 수행 할 수있는 것처럼 보입니다.-위의 예는 WinForms 접근 방식에 가깝습니다. WPF에서 작동하지만 옳지 않습니다. 방법.
BrainSlugs83

1
죄송합니다.이 답변은 잘못된 것입니다. 또한 모든 링크가 끊어졌습니다.
Forest Kunecke 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.