我怎么能把一些文本放入一个文本框,这将被自动删除时,用户键入的东西在它?
当前回答
下面是我的方法是伟大的MVVM,在那里我也检查文本框是否有焦点,你也可以使用一个常规的触发器只是文本值以及重点是,当值改变时,我只是改变背景图像:
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="True"/>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/Images/Scan.PNG" Stretch="Uniform" AlignmentX="Left"/>
</Setter.Value>
</Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
其他回答
只使用XAML,没有扩展,没有转换器:
<Grid>
<TextBox Width="250" VerticalAlignment="Center" HorizontalAlignment="Left" x:Name="SearchTermTextBox" Margin="5"/>
<TextBlock IsHitTestVisible="False" Text="Enter Search Term Here" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchTermTextBox}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
我已经创建了一个简单的代码实现,它适用于WPF和Silverlight:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
public class TextBoxWatermarked : TextBox
{
#region [ Dependency Properties ]
public static DependencyProperty WatermarkProperty = DependencyProperty.Register
(
"Watermark",
typeof(string),
typeof(TextBoxWatermarked),
new PropertyMetadata(new PropertyChangedCallback(OnWatermarkChanged))
);
#endregion
#region [ Fields ]
private bool _isWatermarked;
private Binding _textBinding;
#endregion
#region [ Properties ]
protected new Brush Foreground
{
get { return base.Foreground; }
set { base.Foreground = value; }
}
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
#endregion
#region [ .ctor ]
public TextBoxWatermarked()
{
Loaded += (s, ea) => ShowWatermark();
}
#endregion
#region [ Event Handlers ]
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
HideWatermark();
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
ShowWatermark();
}
private static void OnWatermarkChanged(DependencyObject sender, DependencyPropertyChangedEventArgs ea)
{
var tbw = sender as TextBoxWatermarked;
if (tbw == null) return;
tbw.ShowWatermark();
}
#endregion
#region [ Methods ]
private void ShowWatermark()
{
if (string.IsNullOrEmpty(base.Text))
{
_isWatermarked = true;
base.Foreground = new SolidColorBrush(Colors.Gray);
var bindingExpression = GetBindingExpression(TextProperty);
_textBinding = bindingExpression == null ? null : bindingExpression.ParentBinding;
if (bindingExpression != null)
bindingExpression.UpdateSource();
SetBinding(TextProperty, new Binding());
base.Text = Watermark;
}
}
private void HideWatermark()
{
if (_isWatermarked)
{
_isWatermarked = false;
ClearValue(ForegroundProperty);
base.Text = "";
SetBinding(TextProperty, _textBinding ?? new Binding());
}
}
#endregion
}
用法:
<TextBoxWatermarked Watermark="Some text" />
您可以创建水印,可以添加到任何具有附加属性的文本框。下面是附件属性的来源:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
/// <summary>
/// Class that provides the Watermark attached property
/// </summary>
public static class WatermarkService
{
/// <summary>
/// Watermark Attached Dependency Property
/// </summary>
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
"Watermark",
typeof(object),
typeof(WatermarkService),
new FrameworkPropertyMetadata((object)null, new PropertyChangedCallback(OnWatermarkChanged)));
#region Private Fields
/// <summary>
/// Dictionary of ItemsControls
/// </summary>
private static readonly Dictionary<object, ItemsControl> itemsControls = new Dictionary<object, ItemsControl>();
#endregion
/// <summary>
/// Gets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
/// <returns>The value of the Watermark property</returns>
public static object GetWatermark(DependencyObject d)
{
return (object)d.GetValue(WatermarkProperty);
}
/// <summary>
/// Sets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
/// <param name="value">value of the property</param>
public static void SetWatermark(DependencyObject d, object value)
{
d.SetValue(WatermarkProperty, value);
}
/// <summary>
/// Handles changes to the Watermark property.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = (Control)d;
control.Loaded += Control_Loaded;
if (d is ComboBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
}
else if (d is TextBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
((TextBox)control).TextChanged += Control_GotKeyboardFocus;
}
if (d is ItemsControl && !(d is ComboBox))
{
ItemsControl i = (ItemsControl)d;
// for Items property
i.ItemContainerGenerator.ItemsChanged += ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);
// for ItemsSource property
DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i, ItemsSourceChanged);
}
}
#region Event Handlers
/// <summary>
/// Handle the GotFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_GotKeyboardFocus(object sender, RoutedEventArgs e)
{
Control c = (Control)sender;
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
/// <summary>
/// Handle the Loaded and LostFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_Loaded(object sender, RoutedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
}
/// <summary>
/// Event handler for the items source changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>
private static void ItemsSourceChanged(object sender, EventArgs e)
{
ItemsControl c = (ItemsControl)sender;
if (c.ItemsSource != null)
{
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
else
{
ShowWatermark(c);
}
}
/// <summary>
/// Event handler for the items changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>
private static void ItemsChanged(object sender, ItemsChangedEventArgs e)
{
ItemsControl control;
if (itemsControls.TryGetValue(sender, out control))
{
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
}
#endregion
#region Helper Methods
/// <summary>
/// Remove the watermark from the specified element
/// </summary>
/// <param name="control">Element to remove the watermark from</param>
private static void RemoveWatermark(UIElement control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
Adorner[] adorners = layer.GetAdorners(control);
if (adorners == null)
{
return;
}
foreach (Adorner adorner in adorners)
{
if (adorner is WatermarkAdorner)
{
adorner.Visibility = Visibility.Hidden;
layer.Remove(adorner);
}
}
}
}
/// <summary>
/// Show the watermark on the specified control
/// </summary>
/// <param name="control">Control to show the watermark on</param>
private static void ShowWatermark(Control control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
layer.Add(new WatermarkAdorner(control, GetWatermark(control)));
}
}
/// <summary>
/// Indicates whether or not the watermark should be shown on the specified control
/// </summary>
/// <param name="c"><see cref="Control"/> to test</param>
/// <returns>true if the watermark should be shown; false otherwise</returns>
private static bool ShouldShowWatermark(Control c)
{
if (c is ComboBox)
{
return (c as ComboBox).Text == string.Empty;
}
else if (c is TextBoxBase)
{
return (c as TextBox).Text == string.Empty;
}
else if (c is ItemsControl)
{
return (c as ItemsControl).Items.Count == 0;
}
else
{
return false;
}
}
#endregion
}
附加属性使用一个叫做WatermarkAdorner的类,这里是那个来源:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
/// <summary>
/// Adorner for the watermark
/// </summary>
internal class WatermarkAdorner : Adorner
{
#region Private Fields
/// <summary>
/// <see cref="ContentPresenter"/> that holds the watermark
/// </summary>
private readonly ContentPresenter contentPresenter;
#endregion
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="WatermarkAdorner"/> class
/// </summary>
/// <param name="adornedElement"><see cref="UIElement"/> to be adorned</param>
/// <param name="watermark">The watermark</param>
public WatermarkAdorner(UIElement adornedElement, object watermark) :
base(adornedElement)
{
this.IsHitTestVisible = false;
this.contentPresenter = new ContentPresenter();
this.contentPresenter.Content = watermark;
this.contentPresenter.Opacity = 0.5;
this.contentPresenter.Margin = new Thickness(Control.Margin.Left + Control.Padding.Left, Control.Margin.Top + Control.Padding.Top, 0, 0);
if (this.Control is ItemsControl && !(this.Control is ComboBox))
{
this.contentPresenter.VerticalAlignment = VerticalAlignment.Center;
this.contentPresenter.HorizontalAlignment = HorizontalAlignment.Center;
}
// Hide the control adorner when the adorned element is hidden
Binding binding = new Binding("IsVisible");
binding.Source = adornedElement;
binding.Converter = new BooleanToVisibilityConverter();
this.SetBinding(VisibilityProperty, binding);
}
#endregion
#region Protected Properties
/// <summary>
/// Gets the number of children for the <see cref="ContainerVisual"/>.
/// </summary>
protected override int VisualChildrenCount
{
get { return 1; }
}
#endregion
#region Private Properties
/// <summary>
/// Gets the control that is being adorned
/// </summary>
private Control Control
{
get { return (Control)this.AdornedElement; }
}
#endregion
#region Protected Overrides
/// <summary>
/// Returns a specified child <see cref="Visual"/> for the parent <see cref="ContainerVisual"/>.
/// </summary>
/// <param name="index">A 32-bit signed integer that represents the index value of the child <see cref="Visual"/>. The value of index must be between 0 and <see cref="VisualChildrenCount"/> - 1.</param>
/// <returns>The child <see cref="Visual"/>.</returns>
protected override Visual GetVisualChild(int index)
{
return this.contentPresenter;
}
/// <summary>
/// Implements any custom measuring behavior for the adorner.
/// </summary>
/// <param name="constraint">A size to constrain the adorner to.</param>
/// <returns>A <see cref="Size"/> object representing the amount of layout space needed by the adorner.</returns>
protected override Size MeasureOverride(Size constraint)
{
// Here's the secret to getting the adorner to cover the whole control
this.contentPresenter.Measure(Control.RenderSize);
return Control.RenderSize;
}
/// <summary>
/// When overridden in a derived class, positions child elements and determines a size for a <see cref="FrameworkElement"/> derived class.
/// </summary>
/// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param>
/// <returns>The actual size used.</returns>
protected override Size ArrangeOverride(Size finalSize)
{
this.contentPresenter.Arrange(new Rect(finalSize));
return finalSize;
}
#endregion
}
现在你可以像这样把水印放在任何文本框上:
<AdornerDecorator>
<TextBox x:Name="SearchTextBox">
<controls:WatermarkService.Watermark>
<TextBlock>Type here to search text</TextBlock>
</controls:WatermarkService.Watermark>
</TextBox>
</AdornerDecorator>
水印可以是你想要的任何东西(文本、图像……)。除了适用于文本框,这个水印也适用于组合框和项目控件。
此代码改编自这篇博客文章。
使用风格的简单解决方案:
<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="MM:SS:HH AM/PM" 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>
伟大的解决方案:
https://code.msdn.microsoft.com/windowsdesktop/In-place-hit-messages-for-18db3a6c
<Window.Resources>
<Style x:Key="TextBoxUserStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxVistaStyle" BasedOn="{x:Null}" TargetType="{x:Type PasswordBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<Grid>
<Label x:Name="lblPwd" Content="Password" FontSize="11" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Verdana" Foreground="#828385" Padding="0"/>
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" TargetName="lblPwd" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<PasswordBox Style="{StaticResource PasswordBoxVistaStyle}" Margin="169,143,22,0" Name="txtPassword" FontSize="14" TabIndex="2" Height="31" VerticalAlignment="Top" />
这可以帮助检查您的代码。当应用到密码框时,它将显示密码,当用户输入时,它将消失。
推荐文章
- Linq-to-Entities Join vs GroupJoin
- 为什么字符串类型的默认值是null而不是空字符串?
- 在list中获取不同值的列表
- 组合框:向项目添加文本和值(无绑定源)
- WPF数据绑定:我如何访问“父”数据上下文?
- 如何为ASP.net/C#应用程序配置文件值中的值添加&号
- 从System.Drawing.Bitmap中加载WPF BitmapImage
- 如何找出一个文件存在于c# / .NET?
- 为什么更快地检查字典是否包含键,而不是捕捉异常,以防它不?
- [DataContract]的命名空间
- string. isnullorempty (string) vs. string. isnullowhitespace (string)
- 完全外部连接
- 我应该使用什么MVVM框架?
- 在foreach循环中编辑字典值
- 如何在xml文档中引用泛型类和方法