Bagaimana cara menambahkan teks petunjuk ke kotak teks WPF?

107

Misalnya, Facebook memiliki teks petunjuk "Pencarian" di kotak teks Pencarian saat kotak teks kosong.

Bagaimana cara mencapai ini dengan kotak teks WPF ??

Kotak teks pencarian Facebook

Louis Rhys
sumber
2
Coba cari "spanduk isyarat".
default lokal
@MAKKAM Artikel MSDN ini membahasnya tetapi tidak menunjukkan bagaimana hal itu dilakukan
Louis Rhys
1
Saya tidak akan menyebut apa yang Anda minta sebagai 'teks petunjuk'. bagi saya teks petunjuk adalah jendela munculan. tidak ada yang kurang saya menemukan pertanyaan ini ketika ingin mengatur teks placeholder. dan jawaban di bawah membantu saya.
steve
1
Ngomong

Jawaban:

158

Anda dapat melakukannya dengan lebih mudah dengan a VisualBrushdan beberapa pemicu di 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>

Untuk meningkatkan kegunaan kembali ini Style, Anda juga dapat membuat satu set properti terlampir untuk mengontrol teks spanduk isyarat sebenarnya, warna, orientasi dll.

sellmeadog
sumber
1
Gunakan IsMouseCaptured sebagai ganti IsKeyboardFocused. Begitulah tanggapan spanduk isyarat nyata.
Monstieur
5
Jika ada yang bertanya-tanya bagaimana cara menggunakan properti terlampir untuk meningkatkan penggunaan kembali Style, lihat: stackoverflow.com/a/650620/724944
surfen
@Kurian IsMCaptured akan membuat isyarat menghilang hanya ketika Anda mengkliknya dengan mouse, tetapi akan muncul kembali saat Anda melepaskan tombol mouse. Ini tidak terlihat bagus. IsMouseOver juga tidak akan bagus (keyboard memiliki fokus tetapi penunjuk tetikus ada di tempat lain => isyarat ditampilkan). Kebanyakan spanduk isyarat menggunakan IsKeyboardFocused (Facebook misalnya) dan menurut saya tidak masalah. Solusi alternatifnya adalah menggunakan kedua pemicu: (IsMouseOver OR IsKeyboardFocused)
surfen
23
Solusinya adalah Petunjuk = "Silakan masukkan teks Anda" bukan 20 elemen ... Sayangnya, ini tidak didukung oleh kotak teks
bawaan yang
8
Meskipun pendekatan ini mungkin baik-baik saja untuk kondisi default, itu tidak berfungsi ketika kotak teks Anda sudah berisi sikat latar belakang atau latar belakang formulir tidak memiliki warna yang sama seperti kotak teks.
LWChris
56

Ini adalah solusi sederhana saya, diadaptasi dari 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>
Martin Schmidt
sumber
Pendekatan yang menarik Saya tidak akan langsung memikirkan diri saya sendiri.
itsmatt
bagus dan sederhana :)
shmulik.r
3
Solusi ini bekerja dengan sangat baik jika Anda menyetel TextBlock keIsHitTestVisible="False"
Mage Xy
1
@MageXy mengacu pada TextBlock pertama (petunjuk).
Felix
Solusi ini berfungsi dengan baik jika Anda ingin mengikat teks petunjuk ke properti.
PeterB
11

bagaimana dengan menggunakan materialDesign HintAssist? Saya menggunakan ini yang juga Anda dapat menambahkan petunjuk mengambang juga:

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

Saya menginstal Desain Material dengan Paket Nuget ada panduan instalasi di tautan dokumentasi

Mahdi Khalili
sumber
2
Perpustakaan yang sangat berguna
AlexF11
9

Lakukan di belakang kode dengan menyetel warna teks awalnya menjadi abu-abu dan menambahkan penangan acara untuk mendapatkan dan kehilangan fokus keyboard.

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

Kemudian penangan acara:

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";
        }
    }
}
mxgg250
sumber
7
-1 untuk melakukannya dalam kode di belakang: mengacaukan kontrol, dan ada kemungkinan besar hal ini akan mengganggu logika kontrol lainnya, jika tidak sekarang maka di masa mendatang.
AlexeiOst
4

Anda dapat melakukannya dengan cara yang sangat sederhana. Idenya adalah untuk menempatkan Label di tempat yang sama dengan kotak teks Anda. Label Anda akan terlihat jika kotak teks tidak memiliki teks dan tidak memiliki fokus.

 <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" />

Bonus: Jika Anda ingin memiliki nilai default untuk textBox Anda, pastikan setelah mengaturnya saat mengirimkan data (misalnya: "InputText" = "PlaceHolder Text Here" jika kosong).

makertoo
sumber
2

Pendekatan lain ;-)

ini juga bekerja dengan PasswordBox. Jika ingin menggunakannya dengan TextBox, cukup tukar PasswordChangeddengan 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;
    }
}
Tikar
sumber
Solusi terbaik dan paling sederhana yang saya temukan !! Terima kasih!!
steve
2

Saya pernah mengalami situasi yang sama, saya menyelesaikannya dengan cara berikut. Saya hanya memenuhi persyaratan kotak petunjuk, Anda dapat membuatnya lebih interaktif dengan menambahkan efek dan hal-hal lain pada acara lain seperti fokus, dll.

KODE WPF (Saya telah menghapus gaya agar dapat dibaca)

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

Kode 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;
        }
    }
Mohammad Mahroz
sumber
1

Solusi lain adalah dengan menggunakan toolkit WPF seperti MahApps.Metro. Ini memiliki banyak fitur bagus, seperti tanda air kotak teks:

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

Lihat http://mahapps.com/controls/textbox.html

StefanG
sumber
0

Saya menggunakan acara fokus yang didapat dan hilang:

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

Ini berfungsi dengan baik, tetapi teksnya masih berwarna abu-abu. Perlu dibersihkan. Saya menggunakan VB.NET

StarLordBlair
sumber
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>
DerBesondereEin
sumber
0

Itu pendapat saya:

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

Kebanyakan jawaban lain termasuk yang teratas memiliki kekurangan menurut saya.

Solusi ini berfungsi dalam semua keadaan. XAML murni, mudah digunakan kembali.

Julian
sumber
-1

Saya melakukannya dengan VisualBrushdan beberapa pemicu dalam Styledisarankan oleh: 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: Aplikasi berjalan, bt Desain tidak memuat ... Kesalahan berikut muncul: Referensi jenis ambigu. Jenis bernama 'StaticExtension' muncul di setidaknya dua ruang nama, 'MS.Internal.Metadata.ExposedTypes.Xaml' dan 'System.Windows.Markup'. Pertimbangkan untuk menyesuaikan atribut XmlnsDefinition assembly. sedang menggunakan .net 3.5

SUHAIL AG
sumber
Memecahkan masalah dengan mengubah <Trigger Property="Text" Value="{x:Static sys:String.Empty}">ke<Trigger Property="Text" Value="">
SUHAIL AG
6
Ini tampaknya merupakan tanggapan untuk postingan lain. Harap hanya posting solusi lengkap untuk pertanyaan sebagai jawaban.
Drew Gaynor
4
Jika menurut Anda jawaban @ sellmeadog hampir benar, pertimbangkan untuk memperbaikinya, daripada memposting jawaban baru dengan hampir tidak ada perbedaan.
0xBADF00D
-11

Untuk WPF, tidak ada cara. Anda harus menirunya. Lihat contoh ini . Sekunder (solusi tidak stabil) adalah menjadi tuan rumah kontrol pengguna WinForms yang mewarisi dari TextBox dan mengirim pesan EM_SETCUEBANNER ke kontrol edit. yaitu.

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

Juga, jika Anda ingin menjadi tuan rumah pendekatan kontrol WinForm, saya memiliki kerangka kerja yang sudah menyertakan implementasi ini yang disebut Kerangka Kerja BitFlex, yang dapat Anda unduh secara gratis di sini .

Berikut adalah artikel tentang BitFlex jika Anda menginginkan informasi lebih lanjut. Anda akan mulai menemukan bahwa jika Anda ingin memiliki kontrol gaya Windows Explorer yang umumnya tidak pernah keluar dari kotak, dan karena WPF tidak bekerja dengan pegangan umumnya Anda tidak dapat menulis pembungkus mudah di sekitar Win32 atau kontrol yang ada seperti Anda bisa dengan WinForms.

Tangkapan layar: masukkan deskripsi gambar di sini

David Anderson
sumber
1
wow, kelihatannya agak hackish .. Bagaimana saya bisa melakukan ini saat membuat kontrol pengguna dengan XAML?
Louis Rhys
Kamu tidak. Beginilah cara melakukannya. Jika Anda ingin merangkum ini, buat kontrol pengguna dan properti CueText, dan panggil SetCueText di setter.
David Anderson
Saya kira, OP harus menjadi tuan rumah kontrol winforms, untuk menggunakan pendekatan ini. Atau apakah ada cara untuk mendapatkan pegangan kotak teks?
default lokal
Ini sepertinya sesuatu yang dapat dilakukan secara deklaratif dengan WPF, dengan mengikat apakah kotak teks memiliki fokus atau tidak, dll. - Contoh di atas lebih merupakan pendekatan WinForms - ini akan berfungsi di WPF, tetapi itu tidak benar cara.
BrainSlugs83
2
Maaf, tapi jawaban ini salah. Juga semua tautan rusak.
Forest Kunecke