2012-04-03 65 views
8

在瀏覽MSDN文檔時,您可能會碰到這個gem:TextBox.Watermark。如何在Silverlight 4中使用TextBox.Watermark?

「太棒了!我一直想要一種內置的方式在我的文本框中添加水印!這非常棒,讓我繼續前進,並在XAML中設置!

<TextBox Watermark="This is my watermark" Margin="20"></TextBox> 

不幸的是,如果你運行這個,你不會得到你所期望的:

enter image description here

和詳細信息: enter image description here

這是什麼?那麼,請仔細閱讀MSDN文檔: enter image description here

沒錯。它在Silverlight 4中得到了支持,但它也說「不要在Silverlight 4應用程序中使用」。如果您確實使用它,則會收到System.NotImplemented異常。爲了驗證,這裏是通過反射反編譯屬性的代碼:

[EditorBrowsable(EditorBrowsableState.Never)] 
public object Watermark 
{ 
get 
{ 
StubHelper.ThrowIfNotInDesignMode(); 
return base.GetValue(WatermarkProperty); 
} 
set 
{ 
StubHelper.ThrowIfNotInDesignMode(); 
base.SetValue(WatermarkProperty, value); 
} 
} 

在那裏,它是 - 它拋出一個異常,它不是在設計模式的任何時間。這沒有意義嗎?爲什麼微軟會這樣做?

不幸的是,我還沒有找到任何明確的答案,但是如果我不得不猜測這是因爲微軟正計劃在未來版本(也許是v5)的TextBox控件上實現水印行爲並且希望有效地保留此屬性因此第三方控件創建者不會對TextBox進行子類化並創建自己的Watermark屬性。 我知道至少有一個控件供應商ComponentOne擁有一個從TextBox繼承並提供Watermark屬性的控件。 對我來說,這似乎是微軟阻止人們在他們自己的TextBox子類中使用這個屬性名稱的方式。

回答

14

創建一個類庫項目。添加類文件使用下面的代碼.....之後,添加在此dll在您的項目。

public class WatermarkTextBox : TextBox 
{ 
    private bool displayWatermark = true; 
    private bool hasFocus = false; 
    public WatermarkTextBox() 
    { 
     this.GotFocus += new RoutedEventHandler(WatermarkTextBox_GotFocus); 
     this.LostFocus += new RoutedEventHandler(WatermarkTextBox_LostFocus); 
     this.TextChanged += new TextChangedEventHandler(WatermarkTextBox_TextChanged); 
     this.Unloaded += new RoutedEventHandler(WatermarkTextBox_Unloaded); 
    } 

    private void WatermarkTextBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     if (!hasFocus && Text == "") 
     { 
      setMode(true); 
      displayWatermark = true; 
      this.Text = Watermark; 
     } 
    } 

    private void WatermarkTextBox_Unloaded(object sender, RoutedEventArgs e) 
    { 
     this.GotFocus -= WatermarkTextBox_GotFocus; 
     this.LostFocus -= WatermarkTextBox_LostFocus; 
     this.Unloaded -= WatermarkTextBox_Unloaded; 
     this.TextChanged -= WatermarkTextBox_TextChanged; 
    } 

    private void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e) 
    { 
     hasFocus = true; 
     if (displayWatermark) 
     { 
      setMode(false); 
      this.Text = ""; 
     } 
    } 
    private void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e) 
    { 
     hasFocus = false; 
     if (this.Text == "") 
     { 
      displayWatermark = true; 
      setMode(true); 
      this.Text = Watermark; 
     } 
     else 
     { 
      displayWatermark = false; 
     } 
    } 
    private void setMode(bool watermarkStyle) 
    { 
     if (watermarkStyle) 
     { 
      this.FontStyle = FontStyles.Italic; 
      this.Foreground = new SolidColorBrush(Colors.Gray); 
     } 
     else 
     { 
      this.FontStyle = FontStyles.Normal; 
      this.Foreground = new SolidColorBrush(Colors.Black); 
     } 
    } 
    public new string Watermark 
    { 
     get { return GetValue(WatermarkProperty) as string; } 
     set { SetValue(WatermarkProperty, value); } 
    } 
    public static new readonly DependencyProperty WatermarkProperty = 
     DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata(watermarkPropertyChanged)); 
    private static void watermarkPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     WatermarkTextBox textBox = obj as WatermarkTextBox; 
     if (textBox.displayWatermark) 
     { 
      textBox.Text = e.NewValue.ToString(); 
      textBox.setMode(true); 
     } 
    } 

XAML:

xmlns:watertext="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1" 


    <watertext:WatermarkTextBox Watermark="WElcome" Margin="150,115,120,166"></watertext:WatermarkTextBox> 
+0

+1非常好的解決方案。順便說一句,在Silverlight 5中工作正常。有趣的是,SL5 MSDN文檔仍然具有與Watermark屬性相同的衝突信息。 – 2012-09-05 17:13:40

+0

還要注意,我稍微調整了代碼,主要是爲了解決設計時錯誤(如果未設置水印屬性)。更新的代碼添加爲下面的新答案。 – 2012-09-05 17:53:02

+0

你已經在構造函數中註冊了事件,但是在卸載時你沒有從它們註冊(這很好),但是這帶來了標籤控制的問題,Tab控件將卸載它的內容並在適當的Tab被按下時加載,所以也許你應該註冊到Loaded事件中的事件而不是構造函數。 – Sonosar 2013-07-17 08:15:01

2

那麼你可以成功地在Silverlight使用5

試試這個鏈接: TextBox.Watermark

我成功地使用WatermarkTextBox在Silverlight 5 MVVM應用程序。

3

如果未設置水印屬性,我修正了@mani kandan的解決方案以修復設計時錯誤。還添加了一個HasValue布爾屬性,以便能夠輕鬆檢查用戶是否在文本框中輸入了文本,並最終更改爲將所有空白條目視爲非條目(即繼續顯示水印)。

修改後的代碼:

public class WatermarkTextBox : TextBox 
{ 

    private bool displayWatermark = true; 
    private bool hasFocus = false; 

    public WatermarkTextBox() 
    { 
     this.GotFocus += new RoutedEventHandler(WatermarkTextBox_GotFocus); 
     this.LostFocus += new RoutedEventHandler(WatermarkTextBox_LostFocus); 
     this.TextChanged += new TextChangedEventHandler(WatermarkTextBox_TextChanged); 
     this.Unloaded += new RoutedEventHandler(WatermarkTextBox_Unloaded); 
    } 

    private void WatermarkTextBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     if (!hasFocus && string.IsNullOrWhiteSpace(this.Text)) 
     { 
      setMode(true); 
      displayWatermark = true; 
      // avoid design-time error if Watermark not specified 
      this.Text = (Watermark == null ? string.Empty : Watermark); 
     } 
    } 

    private void WatermarkTextBox_Unloaded(object sender, RoutedEventArgs e) 
    { 
     this.GotFocus -= WatermarkTextBox_GotFocus; 
     this.LostFocus -= WatermarkTextBox_LostFocus; 
     this.Unloaded -= WatermarkTextBox_Unloaded; 
     this.TextChanged -= WatermarkTextBox_TextChanged; 
    } 

    private void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e) 
    { 
     hasFocus = true; 
     if (displayWatermark) 
     { 
      setMode(false); 
      this.Text = ""; 
     } 
    } 

    private void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e) 
    { 
     hasFocus = false; 
     if (string.IsNullOrWhiteSpace(this.Text)) 
     { 
      displayWatermark = true; 
      setMode(true); 
      this.Text = (Watermark == null ? string.Empty : Watermark); 
     } 
     else 
     { 
      displayWatermark = false; 
     } 
    } 

    private void setMode(bool watermarkStyle) 
    { 
     if (watermarkStyle) 
     { 
      this.FontStyle = FontStyles.Italic; 
      this.Foreground = new SolidColorBrush(Colors.Gray); 
     } 
     else 
     { 
      this.FontStyle = FontStyles.Normal; 
      this.Foreground = new SolidColorBrush(Colors.Black); 
     } 
    } 

    public new string Watermark 
    { 
     get { return GetValue(WatermarkProperty) as string; } 
     set { SetValue(WatermarkProperty, value); } 
    } 

    public static new readonly DependencyProperty WatermarkProperty = 
     DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata(watermarkPropertyChanged)); 
    private static void watermarkPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     WatermarkTextBox textBox = obj as WatermarkTextBox; 
     if (textBox.displayWatermark) 
     { 
      textBox.Text = e.NewValue.ToString(); 
      textBox.setMode(true); 
     } 
    } 

    public bool HasValue 
    { 
     get 
     { 
      // if watermark has been specified, then compare to text value to determine if text set by user, 
      // otherwise check to see if empty or whitespace. 
      if (this.Watermark != null) 
       return this.Watermark != this.Text; 
      else 
       return !string.IsNullOrWhiteSpace(this.Text); 
     } 
    } 

} 
2

創建一個類庫項目。添加類文件中使用下面的代碼

using System; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Ink; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 

namespace Project.Controls 
{ 
    public class WatermarkEditBox : TextBox 
    { 

     TextBlock lbl = new TextBlock() 
     { 
      IsHitTestVisible = false, 
      Foreground = new SolidColorBrush(Colors.LightGray), 
      VerticalAlignment = VerticalAlignment.Center, 
      HorizontalAlignment = HorizontalAlignment.Left, 
      Margin = new Thickness(3,0,0,0) 
     }; 
     public string WatermarkText { get { return lbl.Text; } set { lbl.Text = value; } } 

     public WatermarkEditBox() 
     { 
      this.Loaded += WatermarkEditBox_Loaded; 
     } 

     void WatermarkEditBox_Loaded(object sender, RoutedEventArgs e) 
     { 
      this.UpdateLayout(); 
      Grid g = GetObjectOfType<Grid>(this, "RootElement"); 
      if (g != null) 
      { 
       g.Children.Add(lbl); 
      } 
      this.TextChanged += WatermarkEditBox_TextChanged; 
     } 

     void WatermarkEditBox_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      if (this.Text.Length == 0) 
       lbl.Visibility = System.Windows.Visibility.Visible; 
      else 
       lbl.Visibility = System.Windows.Visibility.Collapsed; 
     } 

     public TObject GetObjectOfType<TObject>(DependencyObject parent, string name) where TObject : DependencyObject 
     { 
      int count = VisualTreeHelper.GetChildrenCount(parent); 
      for (int i = 0; i < count; ++i) 
      { 
       DependencyObject child = VisualTreeHelper.GetChild(parent, i); 
       if (child is TObject && child.GetValue(NameProperty).ToString() == name) 
       { 
        return child as TObject; 
       } 
       else 
       { 
        TObject obj = GetObjectOfType<TObject>(child, name); 
        if (obj != null) 
        { 
         return obj; 
        } 
       } 
      } 

      return null; 
     } 

    } 
} 

XAML:

xmlns:Controls="clr-namespace:Project.Controls" 

<Controls:WatermarkEditBox WatermarkText="фильтр" Width="100"/> 
2

看看這個一個基於行爲

namespace MyNamespace 
{ 
    public class WatermarkBehavior : Behavior<TextBox> 
    { 
     public String Watermark 
     { 
      get { return this.GetValue(WatermarkProperty) as String; } 
      set { this.SetValue(WatermarkProperty, value); } 
     } 

     public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(String), typeof(WatermarkBehavior), new PropertyMetadata("", new PropertyChangedCallback(OnWatermarkChanged))); 

     private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var behavior = d as WatermarkBehavior; 
      if (!String.IsNullOrWhiteSpace(e.NewValue as String)) 
      { 
       behavior.SetWatermarkIfNeeded(); 
      } 
     } 

     protected override void OnAttached() 
     { 
      base.OnAttached(); 
      this.AssociatedObject.GotFocus += GotFocus; 
      this.AssociatedObject.LostFocus += LostFocus; 
     } 

     protected override void OnDetaching() 
     { 
      base.OnDetaching(); 
      this.AssociatedObject.GotFocus -= GotFocus; 
      this.AssociatedObject.LostFocus -= LostFocus; 
     } 

     private void GotFocus(object sender, RoutedEventArgs e) 
     { 
      if (this.AssociatedObject.Text == this.Watermark) 
      { 
       this.AssociatedObject.Text = String.Empty; 
       this.AssociatedObject.Foreground = new SolidColorBrush(Colors.Black); 
      } 
     } 

     private void LostFocus(object sender, RoutedEventArgs e) 
     { 
      this.SetWatermarkIfNeeded(); 
     } 

     private void SetWatermarkIfNeeded() 
     { 
      if (String.IsNullOrWhiteSpace(this.AssociatedObject.Text)) 
      { 
       this.SetWatermark(); 
      } 
     } 

     private void SetWatermark() 
     { 
      this.AssociatedObject.Text = this.Watermark; 
      this.AssociatedObject.Foreground = new SolidColorBrush(Colors.Gray); 
     } 
    } 
} 

XAML

<UserControl x:Class="GreenField.Targeting.Controls.BasketTargets.EditorView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:MyNamespace" 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> 
    <TextBox Text="{Binding Text}"> 
    <i:Interaction.Behaviors> 
     <local:WatermarkBehavior Watermark="{Binding Watermark}" /> 
    </i:Interaction.Behaviors> 
    </TextBox> 
</UserControl> 
相關問題