.net 如何在Silverlight 4中使用TextBox.Watermark?

.net 如何在Silverlight 4中使用TextBox.Watermark?,.net,silverlight-4.0,.net,Silverlight 4.0,浏览MSDN文档时,您可能会遇到以下gem:TextBox.Watermark “太棒了!我一直希望有一种内置的方式在我的文本框上做水印!这太棒了,让我继续用XAML设置它吧!” 这就是它——它在任何时候不处于设计模式时都会抛出异常。这没有道理,对吧?微软为什么要这样做 不幸的是,我还没有找到任何明确的答案,但是如果我不得不猜测这是因为微软计划在未来的版本(可能是v5)中在TextBox控件上实现水印行为并希望有效地保留此属性,以便第三方控件创建者不会将TextBox子类化并创建自己的水印属性。

浏览MSDN文档时,您可能会遇到以下gem:TextBox.Watermark

“太棒了!我一直希望有一种内置的方式在我的文本框上做水印!这太棒了,让我继续用XAML设置它吧!”

这就是它——它在任何时候不处于设计模式时都会抛出异常。这没有道理,对吧?微软为什么要这样做

不幸的是,我还没有找到任何明确的答案,但是如果我不得不猜测这是因为微软计划在未来的版本(可能是v5)中在TextBox控件上实现水印行为并希望有效地保留此属性,以便第三方控件创建者不会将TextBox子类化并创建自己的水印属性。 我知道至少有一个控件供应商ComponentOne拥有一个从TextBox继承并提供水印属性的控件。
对我来说,这似乎是微软阻止人们在自己的文本框子类上使用此属性名称的一种方式。

创建一个类库项目。添加类文件使用以下代码…..然后在项目中的此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命名空间:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1”

您可以在Silverlight 5中成功使用它

请尝试以下链接:


我在Silverlight 5 MVVM应用程序中成功地使用了WatermarkTextBox。

我稍微修改了@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);
        }
    }

}

创建一个类库项目。使用以下代码添加类文件

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

    }
}
使用系统;
Net系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Documents;
使用System.Windows.Ink;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Animation;
使用System.Windows.Shapes;
名称空间项目.控件
{
公共类水印编辑框:文本框
{
TextBlock lbl=新的TextBlock()
{
IsHitTestVisible=false,
前景=新的SolidColorBrush(颜色为浅灰色),
垂直对齐=垂直对齐。中心,
水平对齐=水平对齐。左,
余量=新厚度(3,0,0,0)
};
公共字符串水印文本{get{return lbl.Text;}set{lbl.Text=value;}}
公共水印编辑框()
{
this.Loaded+=WatermarkEditBox\u Loaded;
}
已加载无效水印编辑框(对象发送器,路由目标e)
{
this.UpdateLayout();
Grid g=GetObjectOfType(此为“根元素”);
如果(g!=null)
{
g、 儿童。添加(lbl);
}
this.TextChanged+=WatermarkEditBox\u TextChanged;
}
无效水印编辑框\u TextChanged(对象发送者,textchangedventargs e)
{
if(this.Text.Length==0)
lbl.Visibility=System.Windows.Visibility.Visible;
其他的
lbl.Visibility=System.Windows.Visibility.Collapsed;
}
公共ToObject GetObjectOfType(DependencyObject父对象,字符串名称),其中ToObject:DependencyObject
{
int count=VisualTreeHelper.GetChildrenCount(父级);
对于(int i=0;i
XAML:

xmlns:Controls=“clr命名空间:Project.Controls”

根据行为检查此项

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);
        }
    }
}
名称空间MyNamespace
{
公共类水印行为:行为
{
公共字符串水印
{
get{将this.GetValue(WatermarkProperty)作为字符串返回;}
set{this.SetValue(WatermarkProperty,value);}
}
public static readonly dependencProperty WatermarkProperty=dependencProperty.Register(“水印”、typeof(字符串)、typeof(水印行为)、new PropertyMetadata(“、new PropertyChangedCallback(OnWatermarkChanged));
WatermarkChanged上的私有静态无效(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var行为=d为水印行为;
如果(!String.IsNullOrWhiteSpace(如字符串形式的NewValue))
{
behavior.SetWatermarkIfNeeded();
}
}
受保护的覆盖无效附加()
{
base.onatached();
this.AssociatedObject.GotFocus+=GotFocus;
this.AssociatedObject.LostFocus+=LostFocus;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
this.AssociatedObject.GotFocus-=GotFocus;
this.AssociatedObject.LostFocus-=LostFocus;
}
private void GotFocus(对象发送方,RoutedEventArgs e)
{
if(this.AssociatedObject.Text==this.Watermark)
{
this.AssociatedObject.Text=String.Empty;
this.AssociatedObject.前台=新的SolidColorBrush(Colors.Black);
}
}
私有void LostFocus(对象发送方,RoutedEventArgs e)
{
此.SetWatermarkIfNeeded();
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);
        }
    }

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

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

<Controls:WatermarkEditBox WatermarkText="фильтр" Width="100"/>
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);
        }
    }
}
<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>