.net wpf user-interface textbox

.net - ¿Cómo puedo agregar un texto de sugerencia al cuadro de texto de WPF?



user-interface textbox (12)

Por ejemplo, Facebook tiene un texto de sugerencia de "Búsqueda" en el cuadro de texto Buscar cuando el cuadro de texto está vacío.

¿Cómo lograr esto con cuadros de texto WPF?



Esta es mi solución simple, adaptada de 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>


Hágalo en el código subyacente configurando el color del texto inicialmente en gris y agregando controladores de eventos para ganar y perder el enfoque del teclado.

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

Luego, los controladores del evento:

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


Lo logro con VisualBrush y algunos activadores en un Style sugerido por: 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: aplicación ejecutándose, bt Diseño no cargando ... el siguiente error viene: referencia de tipo ambiguo. Un tipo llamado ''StaticExtension'' aparece en al menos dos espacios de nombres, ''MS.Internal.Metadata.ExposedTypes.Xaml'' y ''System.Windows.Markup''. Considere ajustar los atributos de ensamblaje XmlnsDefinition. estoy usando .net 3.5


Otra solución es usar un kit de herramientas de WPF como MahApps.Metro. Tiene muchas características agradables, como una marca de agua de cuadro de texto:

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

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


Otro enfoque ;-)

esto funciona también con PasswordBox . Si desea usarlo con TextBox , simplemente intercambie PasswordChanged con 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>

Código detrás:

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


Para WPF, no hay una manera. Tienes que imitarlo. Mira este ejemplo . Una solución secundaria (escamosa) es alojar un control de usuario de WinForms que hereda de TextBox y enviar el mensaje EM_SETCUEBANNER al control de edición. es decir.

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

Además, si desea alojar un enfoque de control WinForm, tengo un marco que ya incluye esta implementación llamada BitFlex Framework, que puede descargar de forma gratuita aquí .

Aquí hay un artículo sobre BitFlex si desea más información. Comenzará a descubrir que si busca tener controles del estilo del Explorador de Windows, esto generalmente nunca sale de la caja, y dado que WPF no funciona con controladores generalmente no puede escribir un contenedor fácil alrededor de Win32 o un control existente como usted puede con WinForms.

Captura de pantalla:


Puedes hacerlo de una manera muy simple. La idea es colocar una etiqueta en el mismo lugar que su cuadro de texto. Su etiqueta estará visible si el cuadro de texto no tiene texto y no tiene el foco.

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

Bonificación: si desea tener un valor predeterminado para su cuadro de texto, asegúrese de configurarlo al enviar datos (por ejemplo: "Texto de entrada" = "Colocar aquí el texto del encabezado" si está vacío).


Una vez me metí en la misma situación, lo resolví de la siguiente manera. Solo he cumplido con los requisitos de una caja de sugerencias, puedes hacer que sea más interactivo al agregar efectos y otras cosas en otros eventos como en el enfoque, etc.

CÓDIGO WPF (he eliminado el estilo para hacerlo legible)

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


Usé los eventos de enfoque get y lost:

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

Funciona bien, pero el texto está en gris todavía. Necesita limpieza. Estaba usando VB.NET


Puede lograr esto mucho más fácilmente con un VisualBrush y algunos activadores en un 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>

Para aumentar la capacidad de reutilización de este Style , también puede crear un conjunto de propiedades adjuntas para controlar el texto, color, orientación, etc.


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