WPF metin kutusuna nasıl ipucu metni ekleyebilirim?


107

Örneğin, Facebook, metin kutusu boşken Ara metin kutusunda bir "Ara" ipucu metnine sahiptir.

Bunu WPF metin kutuları ile nasıl başarabilirim?

Facebook'un arama metin kutusu


2
"İşaret başlığı" aramayı deneyin.
varsayılan yerel ayar

@MAKKAM bu MSDN makalesi bunu tartışıyor ancak nasıl yapıldığını göstermiyor
Louis Rhys


1
İstediğiniz şeye 'ipucu metni' demezdim. bana ipucu metni bir açılır penceredir. none-the-less Yer tutucu metni ayarlamak istediğimde bu soruyu buldum. ve aşağıdaki cevaplar bana yardımcı oldu.
Steve

1
Bu arada buna filigran denir
Blechdose

Yanıtlar:


158

Bunu a VisualBrushve a'daki bazı tetikleyicilerle çok daha kolay bir şekilde başarabilirsiniz 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>

Bunun yeniden kullanılabilirliğini artırmak için Style, gerçek geçiş afiş metnini, rengini, yönünü vb. Kontrol etmek için bir dizi ek özellik de oluşturabilirsiniz.


1
IsKeyboardFocused yerine IsMouseCaptured'ı kullanın. Gerçek bir işaret pankartı böyle cevap verir.
Monstieur

5

@Kurian IsMouseCaptured, işaretin yalnızca fareyle tıkladığınızda kaybolmasını sağlayacak, ancak fare düğmesini bıraktığınızda yeniden görünecektir. İyi görünmüyor. IsMouseOver da iyi olmaz (klavye odaklıdır ancak fare işaretçisi başka bir yerde => işaret görüntülenir). Çoğu işaret afişi IsKeyboardFocused (örneğin Facebook) kullanıyor ve bence sorun değil. Alternatif çözüm, her iki tetikleyiciyi de kullanmak olabilir: (IsMouseOver OR IsKeyboardFocused)
surfen

23
Çözüm, 20 öğe değil, Hint = "Lütfen metninizi girin" olmalıdır ... Ne yazık ki, bu efsanevi yerleşik metin kutusu tarafından desteklenmiyor ...
Mzn

8
Bu yaklaşım varsayılan koşullar için uygun olsa da, metin kutunuz zaten bir arka plan fırçası içeriyorsa veya form arka planı metin kutusu ile aynı renkte değilse çalışmaz.
LWChris

56

Bu, Microsoft'tan uyarlanmış basit çözümümdür ( 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>

İlginç yaklaşım, hemen kendimi düşünmezdim.
itsmatt

güzel ve basit :)
shmulik.r

3
Bu çözüm özellikle TextBlock'uIsHitTestVisible="False"
Mage Xy

1
@MageXy, ilk TextBlock'a (ipucu olan) atıfta bulunuyor.
Felix

İpucu metnini bir özelliğe bağlamak istiyorsanız bu çözüm harika çalışıyor.
PeterB

11

materialDesign HintAssist'i kullanmaya ne dersiniz? Ben bunu kullanıyorum, ayrıca kayan ipucu da ekleyebilirsiniz:

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

Material Design'ı Nuget Paketi ile kurdum, dokümantasyon bağlantısında kurulum kılavuzu var


2
Çok kullanışlı kütüphane
AlexF11

9

Metin rengini başlangıçta gri olarak ayarlayarak ve klavye odağını kazanmak ve kaybetmek için olay işleyicileri ekleyerek arka planda kodlama yapın.

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

Ardından olay işleyicileri:

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, arkasındaki kodda yapmak için: kontrolü karıştırır ve bu, şimdi değilse, gelecekte diğer kontrol mantığına müdahale etme olasılığı yüksektir.
AlexeiOst


4

Çok basit bir şekilde yapabilirsiniz. Buradaki fikir, metin kutunuzla aynı yere bir Etiket yerleştirmektir. Metin kutusunda metin yoksa ve odak yoksa Etiketiniz görünür olacaktır.

 <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: Metin Kutunuz için varsayılan değere sahip olmak istiyorsanız, veri gönderirken bunu ayarladığınızdan emin olun (örneğin: "InputText" = "Boşsa" Yer Tutucu Metni Buraya Yerleştirin ").


2

Başka bir yaklaşım ;-)

bu aynı zamanda ile de çalışır PasswordBox. Eğer bunu kullanmak istiyorsanız TextBox, basitçe alışverişinde PasswordChangedile 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>

Kodun arkasında:

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

Bulduğum en iyi ve en basit çözüm !! Teşekkürler!!
Steve

2

Bir keresinde aynı duruma girdim, şu şekilde çözdüm. Sadece bir ipucu kutusunun gereksinimlerini yerine getirdim, odaklanma gibi diğer olaylara efektler ve başka şeyler ekleyerek onu daha etkileşimli hale getirebilirsiniz.

WPF KODU (Okunabilir hale getirmek için stili kaldırdım)

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

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

Var ve kaybolan odak olaylarını kullandım:

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

İyi çalışıyor, ancak metin hala gri renkte. Temizlenmesi gerekiyor. VB.NET kullanıyordum


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

Benim alacağım:

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

En iyisi de dahil olmak üzere diğer cevapların çoğunun bence kusurları var.

Bu çözüm her koşulda işe yarar. Saf XAML, kolayca yeniden kullanılabilir.


-1

Ben ile bunu gerçekleştirmek VisualBrushve bazı tetikleyiciler Styleönerdiği: 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: Uygulama çalışıyor, bt Tasarım yüklenmiyor ... Şu Hata geliyor: Belirsiz tür başvurusu. 'StaticExtension' adlı bir tür, en az iki ad alanında bulunur, 'MS.Internal.Metadata.ExposedTypes.Xaml' ve 'System.Windows.Markup'. Assembly XmlnsDefinition özniteliklerini ayarlamayı düşünün. .net 3.5 kullanıyorum


Değiştirerek sorunu çözüldü <Trigger Property="Text" Value="{x:Static sys:String.Empty}">için<Trigger Property="Text" Value="">
SUHAIL AG

6
Bu, başka bir gönderiye bir yanıt gibi görünüyor. Lütfen yanıt olarak soruya yalnızca eksiksiz çözümler gönderin.
Drew Gaynor

4
@ Sellmeadog'un yanıtının neredeyse doğru olduğunu düşünüyorsanız, neredeyse hiçbir fark olmadan yeni bir yanıt göndermek yerine düzeltmeyi düşünün.
0xBADF00D

-11

WPF için bir yol yok. Onu taklit etmelisin. Bu örneğe bakın . İkincil (hatalı çözüm), TextBox'tan devralan bir WinForms kullanıcı kontrolünü barındırmak ve EM_SETCUEBANNER mesajını düzenleme kontrolüne göndermektir. yani.

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

Ayrıca, bir WinForm kontrol yaklaşımına ev sahipliği yapmak istiyorsanız, buradan ücretsiz olarak indirebileceğiniz BitFlex Framework adlı bu uygulamayı zaten içeren bir çerçevem var .

Daha fazla bilgi istiyorsanız BitFlex hakkında bir makale . Windows Gezgini tarzı kontrollere sahip olmak istiyorsanız, bunun genellikle kutudan çıkmadığını ve WPF'nin genellikle tutamaçlarla çalışmadığını görmeye başlayacaksınız ve Win32 veya sizin gibi mevcut bir kontrol etrafında kolay bir sarmalayıcı yazamayacaksınız. WinForms ile.

Ekran görüntüsü: görüntü açıklamasını buraya girin


1
vay, bu biraz hile gibi görünüyor .. XAML ile bir kullanıcı denetimi oluştururken bunu nasıl yapabilirim?
Louis Rhys

Yapmıyorsun. Bu nasıl yapılır. Bunu kapsüllemek istiyorsanız, bir kullanıcı denetimi ve bir CueText özelliği yapın ve ayarlayıcıda SetCueText'i çağırın.
David Anderson

Sanırım OP, bu yaklaşımı kullanmak için winforms kontrollerini barındırmalı. Veya metin kutusu tanıtıcısı almanın bir yolu var mı?
varsayılan yerel ayar

Bu, metin kutusunun odağa sahip olup olmadığına bağlı olarak WPF ile bildirimsel olarak yapılabilecek bir şey gibi görünüyor. - Yukarıdaki örnek daha çok bir WinForms yaklaşımıdır - WPF'de çalışacaktır, ancak doğru değildir yol.
BrainSlugs83

2
Üzgünüz, ancak bu cevap tamamen yanlış. Ayrıca tüm bağlantılar kopmuştur.
Forest Kunecke
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.