Facebook hat beispielsweise einen Hinweistext "Suchen" im Textfeld "Suchen", wenn das Textfeld leer ist.
Wie erreicht man das mit WPF-Textfeldern?
Facebook hat beispielsweise einen Hinweistext "Suchen" im Textfeld "Suchen", wenn das Textfeld leer ist.
Wie erreicht man das mit WPF-Textfeldern?
Antworten:
Sie können dies viel einfacher mit a VisualBrush
und einigen Auslösern in a erreichen 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>
Um die Wiederverwendbarkeit zu verbessern Style
, können Sie auch eine Reihe von angehängten Eigenschaften erstellen, um den tatsächlichen Text, die Farbe, die Ausrichtung usw. des Cue-Banners zu steuern.
Dies ist meine einfache Lösung, angepasst von 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>
IsHitTestVisible="False"
Was ist mit materialDesign HintAssist? Ich benutze dies, was Sie auch schwebende Hinweise hinzufügen können:
<TextBox Width="150" Height="40" Text="hello" materialDesign:HintAssist.Hint="address" materialDesign:HintAssist.IsFloating="True"></TextBox>
i installierte Material Design mit Nuget Paket dort Installationsanleitung in ist Dokumentation Link
Tun Sie dies im Code-Behind, indem Sie die Textfarbe zunächst auf Grau setzen und Ereignishandler hinzufügen, um den Tastaturfokus zu gewinnen und zu verlieren.
TextBox tb = new TextBox();
tb.Foreground = Brushes.Gray;
tb.Text = "Text";
tb.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_GotKeyboardFocus);
tb.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_LostKeyboardFocus);
Dann die Event-Handler:
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";
}
}
}
Sie müssen ein benutzerdefiniertes Steuerelement erstellen, indem Sie das Textfeld erben. Der folgende Link enthält ein hervorragendes Beispiel für das Beispiel eines Suchtextfelds. Bitte schauen Sie sich das an
http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/
Sie können dies auf sehr einfache Weise tun. Die Idee ist, ein Etikett an der gleichen Stelle wie Ihr Textfeld zu platzieren. Ihr Etikett wird angezeigt, wenn das Textfeld keinen Text und keinen Fokus enthält.
<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: Wenn Sie einen Standardwert für Ihre TextBox haben möchten, müssen Sie diesen nach dem Senden von Daten festlegen (zum Beispiel: "InputText" = "PlaceHolder Text Here", falls leer).
Ein anderer Ansatz ;-)
das funktioniert auch mit PasswordBox
. Wenn Sie es mit verwenden möchten TextBox
, tauschen Sie es einfach PasswordChanged
mit aus 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;
}
}
Ich bin einmal in die gleiche Situation geraten und habe sie folgendermaßen gelöst. Ich habe nur die Anforderungen eines Hinweisfelds erfüllt. Sie können es interaktiver gestalten, indem Sie Effekte und andere Dinge zu anderen Ereignissen wie Fokus usw. hinzufügen.
WPF-CODE (Ich habe das Styling entfernt, um es lesbar zu machen)
<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 # -Code
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;
}
}
Eine andere Lösung ist die Verwendung eines WPF-Toolkits wie MahApps.Metro. Es hat viele schöne Funktionen, wie ein Textfeld Wasserzeichen:
Controls:TextBoxHelper.Watermark="Search..."
Ich habe die Ereignisse zum Erhalten und Verlieren des Fokus verwendet:
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
Es funktioniert gut, aber der Text ist immer noch grau. Muss aufgeräumt werden. Ich habe VB.NET verwendet
<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>
Das ist meine Meinung:
<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>
Die meisten anderen Antworten, einschließlich der obersten, weisen meiner Meinung nach Mängel auf.
Diese Lösung funktioniert unter allen Umständen. Pure XAML, leicht wiederverwendbar.
Ich erreiche dies mit einem VisualBrush
und einigen Auslösern in einem Style
Vorschlag von : 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: Anwendung läuft, bt Design wird nicht geladen ... der folgende Fehler tritt auf: Mehrdeutige Typreferenz . Ein Typ mit dem Namen 'StaticExtension' kommt in mindestens zwei Namespaces vor: 'MS.Internal.Metadata.ExposedTypes.Xaml' und 'System.Windows.Markup'. Ziehen Sie in Betracht, die XmlnsDefinition-Attribute der Assembly anzupassen. Ich verwende .net 3.5
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
zu<Trigger Property="Text" Value="">
Für WPF gibt es keinen Weg. Du musst es nachahmen. Siehe dieses Beispiel . Eine sekundäre (flockige Lösung) besteht darin, ein WinForms-Benutzersteuerelement zu hosten, das von TextBox erbt, und die Nachricht EM_SETCUEBANNER an das Bearbeitungssteuerelement zu senden. dh.
[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);
}
Wenn Sie einen WinForm-Steuerungsansatz hosten möchten, habe ich bereits ein Framework namens BitFlex Framework, das diese Implementierung enthält und das Sie hier kostenlos herunterladen können .
Hier ist ein Artikel über BitFlex, wenn Sie weitere Informationen wünschen. Sie werden feststellen, dass wenn Sie nach Steuerelementen im Windows Explorer-Stil suchen, diese im Allgemeinen nie sofort verfügbar sind. Da WPF im Allgemeinen nicht mit Handles funktioniert, können Sie keinen einfachen Wrapper um Win32 oder ein vorhandenes Steuerelement schreiben, wie Sie es können mit WinForms.
Bildschirmfoto: