2011-09-15 41 views
76

例如,當文本框爲空時,Facebook在搜索文本框中有一個「搜索」提示文本。如何向WPF文本框添加提示文本?

如何用WPF文本框實現這個?

Facebook's search textbox

+0

嘗試搜索 「提示旗幟」。 –

+0

@MAKKAM [此MSDN文章](http://msdn.microsoft.com/en-us/library/bb775793%28v=vs.85%29.aspx#cue_banner)對此進行了討論,但並未顯示它是如何完成的 –

+1

也見http://stackoverflow.com/questions/833943/watermark-textbox-in-wpf – OneWorld

回答

-10

對於WPF,沒有辦法。你必須模仿它。 See this example。輔助(片狀解決方案)是承載從TextBox繼承的WinForms用戶控件,並將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框架,它可以download for free here

Here is an article關於BitFlex如果您想了解更多信息。您將開始發現,如果您希望擁有Windows資源管理器樣式的控件,但通常情況下永遠不會出現這種情況,並且因爲WPF通常不能處理句柄,所以無法在Win32或現有控件上編寫簡單的包裝,例如與WinForms。

截圖: enter image description here

+1

哇,這看起來有點hackish ..我怎樣才能做到這一點,用XAML創建用戶控制? –

+0

你不知道。這是如何完成的。如果你想封裝這個,那麼創建一個用戶控件和一個CueText屬性,並在setter中調用SetCueText。 –

+0

我想,OP應該託管winforms控件,以使用這種方法。或者有沒有辦法讓文本框處理? –

129

你可以在一個Style也更容易與VisualBrush和一些觸發器大有作爲這樣的:

<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的可重用性,您還可以創建一組附加的屬性來控制實際的提示橫幅文本,顏色,方向等。

+1

使用IsMouseCaptured而不是IsKeyboardFocused。這就是真正的提示標語如何迴應。 – Monstieur

+3

如果有人想知道如何使用附加的屬性來增加樣式的可重用性,請參閱:http://stackoverflow.com/a/650620/724944 – surfen

+0

@Kurian IsMouseCaptured將使cue消失,只有當您用鼠標單擊它時,纔會出現再次釋放鼠標按鈕時。它看起來不太好。 IsMouseOver也不會很好(鍵盤具有焦點,但鼠標指針在別處=>提示顯示)。大多數提示橫幅使用IsKeyboardFocused(Facebook例如),我認爲這很好。另一種解決方案是使用兩種觸發器:(IsMouseOver或IsKeyboardFocused) – surfen

10

在代碼後面通過設置將文本顏色初始化爲灰色並添加用於獲取和失去鍵盤焦點的事件處理程序。

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

-1因爲在後面的代碼中執行它:使控制混亂,並且很有可能會干擾其他控制邏輯,如果不是現在,那麼將來也是如此。 – AlexeiOst

0

我使用GOT和失去焦點事件:

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

-2

我通過VisualBrushStyle中的一些觸發器完成了此操作: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設計不加載...以下錯誤出現: 歧義類型引用。名爲'StaticExtension'的類型至少出現在兩個名稱空間'MS.Internal.Metadata.ExposedTypes.Xaml'和'System.Windows.Markup'中。考慮調整程序集XmlnsDefinition屬性。 「M使用.net 3.5

+0

通過更改''解決了問題''' –

+5

這似乎是對另一篇文章的回覆。請僅將問題的完整解決方案作爲答案發布。 –

+4

如果您認爲@ sellmeadog的回答幾乎是正確的,請考慮更正它,而不是發佈幾乎沒有區別的新答案。 – 0xBADF00D

37

這是我簡單的解決方案,改編自微軟(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> 
+0

有趣的方法我不會馬上想到自己。 – itsmatt

+0

很好,很簡單:) –

+1

如果你設置TextBlock爲'IsHitTestVisible ='False'' –

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

另一個方法;-)

這個作品也有PasswordBox。如果您想與TextBox一起使用,只需將PasswordChangedTextChanged兌換即可。

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

你可以在一個非常簡單的方式做。 這個想法是將標籤放置在與您的文本框相同的位置。如果文本框沒有文本並且沒有焦點,您的標籤將會顯示。

<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的」 =「佔位符文本這裏」如果爲空)。

1

有一次,我到了同樣的情況,我解決它下面的方式。 我只完成一個提示框的要求,你可以把它更具互動性,加入其他的事件,如焦點等

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