ตัวอย่างเช่น Facebook มีข้อความคำใบ้ "ค้นหา" ในกล่องข้อความค้นหาเมื่อกล่องข้อความว่างเปล่า
จะบรรลุสิ่งนี้ด้วยกล่องข้อความ WPF ได้อย่างไร ??
ตัวอย่างเช่น Facebook มีข้อความคำใบ้ "ค้นหา" ในกล่องข้อความค้นหาเมื่อกล่องข้อความว่างเปล่า
จะบรรลุสิ่งนี้ด้วยกล่องข้อความ WPF ได้อย่างไร ??
คำตอบ:
คุณสามารถทำสิ่งนี้ได้ง่ายขึ้นด้วย 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>
เพื่อเพิ่มความสามารถในการใช้ซ้ำได้Style
คุณยังสามารถสร้างชุดคุณสมบัติที่แนบมาเพื่อควบคุมข้อความแบนเนอร์คิวสีการวางแนว ฯลฯ
นี่เป็นวิธีง่ายๆของฉันซึ่งดัดแปลงมาจาก 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}}" IsHitTestVisible="False"/>
<!-- enter term here -->
<TextBox MinWidth="50" Name="txtSearchBox" Background="Transparent" />
</Grid>
IsHitTestVisible="False"
แล้วการใช้MaterialDesign HintAssist ล่ะ? ฉันกำลังใช้สิ่งนี้ซึ่งคุณสามารถเพิ่มคำใบ้ลอยได้ด้วย:
<TextBox Width="150" Height="40" Text="hello" materialDesign:HintAssist.Hint="address" materialDesign:HintAssist.IsFloating="True"></TextBox>
ฉันติดตั้ง Material Design ด้วย Nuget Package มีคู่มือการติดตั้งในลิงค์เอกสาร
ทำในโค้ดหลังโดยตั้งค่าสีข้อความในตอนแรกเป็นสีเทาและเพิ่มตัวจัดการเหตุการณ์เพื่อให้ได้มาซึ่งและสูญเสียโฟกัสของแป้นพิมพ์
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";
}
}
}
คุณต้องสร้างตัวควบคุมแบบกำหนดเองโดยการสืบทอดกล่องข้อความ ลิงค์ด้านล่างมีตัวอย่างที่ยอดเยี่ยมเกี่ยวกับตัวอย่างช่องข้อความค้นหา โปรดดูที่นี่
http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/
คุณสามารถทำได้ด้วยวิธีง่ายๆ แนวคิดคือการวางป้ายกำกับไว้ที่เดียวกับกล่องข้อความของคุณ ป้ายกำกับของคุณจะมองเห็นได้หากกล่องข้อความไม่มีข้อความและไม่มีโฟกัส
<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" />
โบนัส: หากคุณต้องการมีค่าเริ่มต้นสำหรับกล่องข้อความของคุณโปรดตรวจสอบให้แน่ใจว่าได้ตั้งค่าหลังจากส่งข้อมูลแล้ว (ตัวอย่างเช่น "InputText" = "PlaceHolder Text Here" หากว่างเปล่า)
ครั้งหนึ่งฉันตกอยู่ในสถานการณ์เดียวกันฉันแก้ไขด้วยวิธีต่อไปนี้ ฉันทำตามข้อกำหนดของกล่องคำใบ้เท่านั้นคุณสามารถทำให้มันโต้ตอบได้มากขึ้นโดยการเพิ่มเอฟเฟกต์และสิ่งอื่น ๆ ในกิจกรรมอื่น ๆ เช่นการโฟกัสเป็นต้น
WPF CODE (ฉันได้ลบรูปแบบเพื่อให้อ่านได้)
<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;
}
}
อีกแนวทาง ;-)
สิ่งนี้ใช้ได้กับ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>
รหัสหลัง:
private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
{
txtHintPassword.Visibility = Visibility.Visible;
if (txtPassword.Password.Length > 0)
{
txtHintPassword.Visibility = Visibility.Hidden;
}
}
IsHitTestVisible="False"
เพื่อให้แน่ใจว่าผู้ใช้คลิกที่ใดก็ตามจะถูกส่งต่อไปยังการควบคุมที่ถูกต้อง?
อีกวิธีหนึ่งคือการใช้ชุดเครื่องมือ WPF เช่น MahApps.Metro มีคุณสมบัติที่ดีมากมายเช่นลายน้ำกล่องข้อความ:
Controls:TextBoxHelper.Watermark="Search..."
ฉันใช้เหตุการณ์โฟกัสได้และหายไป:
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
<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>
นั่นคือสิ่งที่ฉันใช้:
<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 บริสุทธิ์สามารถนำกลับมาใช้ใหม่ได้อย่างง่ายดาย
ที่ผมทำสำเร็จนี้ด้วย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 Design ไม่โหลด ... เกิดข้อผิดพลาดต่อไปนี้: การอ้างอิงประเภทไม่ชัดเจน ประเภทที่ชื่อว่า 'StaticExtension' เกิดขึ้นในอย่างน้อยสองเนมสเปซ 'MS.Internal.Metadata.ExposedTypes.Xaml' และ 'System.Windows.Markup' พิจารณาปรับแอ็ตทริบิวต์ XmlnsDefinition แอสเซมบลี 'm โดยใช้. net 3.5
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
เป็น<Trigger Property="Text" Value="">
สำหรับ WPF ไม่มีทาง คุณต้องเลียนแบบมัน ดูตัวอย่างนี้ รอง (โซลูชันที่ไม่สม่ำเสมอ) คือการโฮสต์ตัวควบคุมผู้ใช้ WinForms ที่สืบทอดมาจาก TextBox และส่งข้อความ 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 Explorer ที่โดยทั่วไปแล้วสิ่งนี้จะไม่หลุดออกจากกรอบและเนื่องจาก WPF ไม่ทำงานกับที่จับโดยทั่วไปคุณจึงไม่สามารถเขียน wrapper แบบง่ายรอบ ๆ Win32 หรือตัวควบคุมที่มีอยู่อย่างที่คุณทำได้ ด้วย WinForms
ภาพหน้าจอ: