Làm cách nào để thêm văn bản gợi ý vào hộp văn bản WPF?


107

Ví dụ: Facebook có văn bản gợi ý "Tìm kiếm" trong hộp văn bản Tìm kiếm khi hộp văn bản trống.

Làm thế nào để đạt được điều này với các hộp văn bản WPF ??

Hộp văn bản tìm kiếm của Facebook


2
Cố gắng tìm kiếm "biểu ngữ cái".
ngôn ngữ mặc định

@MAKKAM bài viết MSDN này thảo luận về nó nhưng nó không cho thấy nó được thực hiện như thế nào
Louis Rhys


1
Tôi sẽ không gọi những gì bạn đang yêu cầu là 'văn bản gợi ý'. với tôi văn bản gợi ý là một cửa sổ bật lên. Tôi đã tìm thấy câu hỏi này khi muốn thiết lập văn bản giữ chỗ. và câu trả lời dưới đây đã giúp tôi.
steve

1
Đó được gọi là watermark bằng cách này
Blechdose

Câu trả lời:


158

Bạn có thể thực hiện điều này dễ dàng hơn nhiều với một VisualBrushvà một số trình kích hoạt trong 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>

Để tăng khả năng tái sử dụng của điều này Style, bạn cũng có thể tạo một tập hợp các thuộc tính đính kèm để kiểm soát văn bản biểu ngữ gợi ý thực tế, màu sắc, hướng, v.v.


1
Sử dụng IsMouseCaptured thay vì IsKeyboardFocused. Đó là cách một biểu ngữ gợi ý thực sự phản hồi.
Monstieur

5
Nếu ai đó tự hỏi làm thế nào để sử dụng các thuộc tính đính kèm để tăng khả năng tái sử dụng Kiểu, hãy xem: stackoverflow.com/a/650620/724944
Suren

@Kurian IsMouseCaptured sẽ làm cho gợi ý chỉ biến mất khi bạn nhấp vào nó bằng chuột, nhưng sẽ xuất hiện lại khi bạn thả nút chuột. Nó trông không đẹp. IsMouseOver cũng sẽ không tốt (bàn phím có tiêu điểm nhưng con trỏ chuột ở chỗ khác => hiển thị dấu hiệu). Hầu hết các biểu ngữ gợi ý sử dụng IsKeyboardFocused (Facebook chẳng hạn) và tôi nghĩ nó ổn. Giải pháp thay thế sẽ được sử dụng cả hai gây nên: (IsMouseOver HOẶC IsKeyboardFocused)
surfen

23
Các giải pháp cần được Gợi ý = "Vui lòng nhập văn bản của bạn" không 20 yếu tố ... Than ôi, điều này không được hỗ trợ bởi những huyền thoại được xây dựng trong hộp văn bản ...
MZN

8
Mặc dù cách tiếp cận này có thể ổn đối với các điều kiện mặc định, nhưng nó không hoạt động khi hộp văn bản của bạn đã chứa bút vẽ nền hoặc nền biểu mẫu không cùng màu với hộp văn bản.
LWChris

56

Đây là giải pháp đơn giản của tôi, được điều chỉnh từ 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>

Cách tiếp cận thú vị mà tôi không nghĩ đến ngay lập tức.
itmatt

tốt đẹp và đơn giản :)
shmulik.r

3
Giải pháp này làm việc đặc biệt tốt nếu bạn thiết lập các TextBlock đểIsHitTestVisible="False"
Mage Xy

1
@MageXy đang đề cập đến TextBlock đầu tiên (gợi ý).
Felix

Giải pháp này hoạt động tốt nếu bạn muốn liên kết văn bản gợi ý với một thuộc tính.
PeterB

11

còn việc sử dụng materialDesign HintAssist thì sao? Tôi đang sử dụng cái này, bạn cũng có thể thêm gợi ý nổi:

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

Tôi đã cài đặt Material Design với Nuget Package có hướng dẫn cài đặt trong liên kết tài liệu


2
Thư viện rất hữu ích
AlexF11

9

Thực hiện điều đó ở đoạn mã phía sau bằng cách đặt màu văn bản ban đầu thành màu xám và thêm trình xử lý sự kiện để tăng và mất tiêu điểm bàn phím.

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

Sau đó, các trình xử lý sự kiện:

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 vì làm điều đó trong mã phía sau: làm lộn xộn điều khiển và có nhiều khả năng điều này sẽ ảnh hưởng đến logic điều khiển khác, nếu không phải bây giờ thì trong tương lai.
AlexeiOst


4

Bạn có thể làm một cách rất đơn giản. Ý tưởng là đặt Nhãn ở cùng vị trí với hộp văn bản của bạn. Nhãn của bạn sẽ hiển thị nếu hộp văn bản không có văn bản và không có tiêu điểm.

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

Phần thưởng: Nếu bạn muốn đặt giá trị mặc định cho textBox của mình, hãy đảm bảo sau khi đặt giá trị đó khi gửi dữ liệu (ví dụ: "InputText" = "PlaceHolder Text Here" nếu trống).


2

Cách tiếp cận khác ;-)

điều này cũng hoạt động với PasswordBox. Nếu bạn muốn sử dụng nó TextBox, chỉ cần trao đổi PasswordChangedvới 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>

Mã ẩn:

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

Giải pháp tốt nhất và đơn giản nhất mà tôi đã tìm thấy !! Cảm ơn!!
steve

2

Tôi đã từng rơi vào trường hợp tương tự, tôi đã giải quyết nó theo cách sau. Tôi chỉ đáp ứng các yêu cầu của hộp gợi ý, bạn có thể làm cho nó tương tác hơn bằng cách thêm hiệu ứng và những thứ khác vào các sự kiện khác như tiêu điểm, v.v.

WPF CODE (Tôi đã xóa kiểu để làm cho nó có thể đọc được)

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

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


0

Tôi đã sử dụng các sự kiện được và mất tiêu điể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

Nó hoạt động tốt, nhưng văn bản vẫn có màu xám. Cần dọn dẹp. Tôi đã sử dụng VB.NET


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

Đó là lý do của tôi:

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

Theo quan điểm của tôi, hầu hết các câu trả lời khác bao gồm cả câu trả lời hàng đầu đều có sai sót.

Giải pháp này hoạt động trong mọi trường hợp. XAML tinh khiết, dễ dàng tái sử dụng.


-1

Tôi thực hiện điều này với một VisualBrushvà một số trigger trong một Styleđề xuất bở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: Ứng dụng đang chạy, bt Thiết kế không tải ... lỗi sau xuất hiện: Tham chiếu kiểu không rõ ràng. Một kiểu có tên 'StaticExtension' xuất hiện trong ít nhất hai không gian tên, 'MS.Internal.Metadata.ExposedTypes.Xaml' và 'System.Windows.Markup'. Xem xét điều chỉnh các thuộc tính assembly XmlnsDefinition. đang sử dụng .net 3.5


Đã giải quyết vấn đề bằng cách thay đổi <Trigger Property="Text" Value="{x:Static sys:String.Empty}">thành<Trigger Property="Text" Value="">
SUHAIL AG

6
Đây dường như là một phản hồi cho một bài đăng khác. Vui lòng chỉ đăng các giải pháp hoàn chỉnh cho câu hỏi dưới dạng câu trả lời.
Drew Gaynor

4
Nếu bạn cho rằng câu trả lời của @ sellmeadog gần đúng, hãy cân nhắc sửa nó, thay vì đăng một câu trả lời mới gần như không có sự khác biệt.
0xBADF00D

-11

Đối với WPF, không có cách nào. Bạn phải bắt chước nó. Hãy xem ví dụ này . Giải pháp thứ cấp (giải pháp không ổn định) là lưu trữ điều khiển người dùng WinForms kế thừa từ TextBox và gửi thông báo EM_SETCUEBANNER tới điều khiển chỉnh sửa. I E.

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

Ngoài ra, nếu bạn muốn lưu trữ phương pháp điều khiển WinForm, tôi có một khuôn khổ đã bao gồm triển khai này được gọi là BitFlex Framework, bạn có thể tải xuống miễn phí tại đây .

Đây là một bài báo về BitFlex nếu bạn muốn biết thêm thông tin. Bạn sẽ bắt đầu thấy rằng nếu bạn đang muốn có các điều khiển kiểu Windows Explorer mà điều này thường không bao giờ xuất hiện trong hộp và vì WPF không hoạt động với các tay cầm nên thường bạn không thể viết một trình bao bọc dễ dàng xung quanh Win32 hoặc một điều khiển hiện có như bạn có thể với WinForms.

Ảnh chụp màn hình: nhập mô tả hình ảnh ở đây


1
wow, trông hơi khó hiểu .. Làm cách nào để thực hiện việc này khi tạo điều khiển người dùng với XAML?
Louis Rhys

Bạn không. Đây là cách nó được thực hiện. Nếu bạn muốn đóng gói điều này, hãy tạo điều khiển người dùng và thuộc tính CueText và gọi SetCueText trong setter.
David Anderson,

Tôi đoán, OP nên lưu trữ các điều khiển winforms để sử dụng phương pháp này. Hoặc có cách nào để có được hộp văn bản xử lý không?
ngôn ngữ mặc định

Điều này có vẻ giống như một cái gì đó có thể được thực hiện một cách khai báo với WPF, bằng cách ràng buộc với việc hộp văn bản có tiêu điểm hay không, v.v. - Ví dụ trên là cách tiếp cận WinForms nhiều hơn - nó sẽ hoạt động trong WPF, nhưng nó không đúng đường.
BrainSlugs83

1
Xin lỗi, nhưng câu trả lời này chỉ đơn giản là không chính xác. Ngoài ra tất cả các liên kết đều bị hỏng.
Forest Kunecke,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.