我怎么能把一些文本放入一个文本框,这将被自动删除时,用户键入的东西在它?
当前回答
下面是XAML中另一个简单的解决方案:
XAML:
<TextBox>
<TextBox.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<!--text color-->
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Text" Value=""/>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<!--placeholder color-->
<Setter Property="Foreground" Value="Gray"/>
<!--placeholder here-->
<Setter Property="Text" Value="Placeholder"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Resources>
</TextBox>
其他回答
好吧,这是我的:不一定是最好的,但因为它很简单,很容易编辑到你的口味。
<UserControl x:Class="WPFControls.ShadowedTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFControls"
Name="Root">
<UserControl.Resources>
<local:ShadowConverter x:Key="ShadowConvert"/>
</UserControl.Resources>
<Grid>
<TextBox Name="textBox"
Foreground="{Binding ElementName=Root, Path=Foreground}"
Text="{Binding ElementName=Root, Path=Text, UpdateSourceTrigger=PropertyChanged}"
TextChanged="textBox_TextChanged"
TextWrapping="Wrap"
VerticalContentAlignment="Center"/>
<TextBlock Name="WaterMarkLabel"
IsHitTestVisible="False"
Foreground="{Binding ElementName=Root,Path=Foreground}"
FontWeight="Thin"
Opacity=".345"
FontStyle="Italic"
Text="{Binding ElementName=Root, Path=Watermark}"
VerticalAlignment="Center"
TextWrapping="Wrap"
TextAlignment="Center">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource ShadowConvert}">
<Binding ElementName="textBox" Path="Text"/>
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
</Grid>
这个转换器,就像它现在写的那样,它不一定是一个MultiConverter,但这样它可以很容易地扩展
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPFControls
{
class ShadowConverter:IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var text = (string) values[0];
return text == string.Empty
? Visibility.Visible
: Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new object[0];
}
#endregion
}
}
最后是背后的代码:
using System.Windows;
using System.Windows.Controls;
namespace WPFControls
{
/// <summary>
/// Interaction logic for ShadowedTextBox.xaml
/// </summary>
public partial class ShadowedTextBox : UserControl
{
public event TextChangedEventHandler TextChanged;
public ShadowedTextBox()
{
InitializeComponent();
}
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.Register("Watermark",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextChangedProperty =
DependencyProperty.Register("TextChanged",
typeof (TextChangedEventHandler),
typeof (ShadowedTextBox),
new UIPropertyMetadata(null));
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set
{
SetValue(WatermarkProperty, value);
}
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set{SetValue(TextProperty,value);}
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (TextChanged != null) TextChanged(this, e);
}
public void Clear()
{
textBox.Clear();
}
}
}
<TextBox Controls:TextBoxHelper.Watermark="Watermark"/>
添加mahapps。地铁到你的项目。 将带有上述代码的文本框添加到窗口中。
我决定通过一个行为来解决这个问题。它使用Hint属性定义要显示的文本(如果您愿意,也可以是一个对象),并使用Value属性计算提示是否应该可见。
行为声明如下:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;
using System.Windows.Media;
public class HintBehavior : Behavior<ContentControl>
{
public static readonly DependencyProperty HintProperty = DependencyProperty
.Register("Hint", typeof (string), typeof (HintBehavior)
//, new FrameworkPropertyMetadata(null, OnHintChanged)
);
public string Hint
{
get { return (string) GetValue(HintProperty); }
set { SetValue(HintProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty
.Register("Value", typeof (object), typeof (HintBehavior)
, new FrameworkPropertyMetadata(null, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var visible = e.NewValue == null;
d.SetValue(VisibilityProperty, visible ? Visibility.Visible : Visibility.Collapsed);
}
public object Value
{
get { return GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty VisibilityProperty = DependencyProperty
.Register("Visibility", typeof (Visibility), typeof (HintBehavior)
, new FrameworkPropertyMetadata(Visibility.Visible
//, new PropertyChangedCallback(OnVisibilityChanged)
));
public Visibility Visibility
{
get { return (Visibility) GetValue(VisibilityProperty); }
set { SetValue(VisibilityProperty, value); }
}
public static readonly DependencyProperty ForegroundProperty = DependencyProperty
.Register("Foreground", typeof (Brush), typeof (HintBehavior)
, new FrameworkPropertyMetadata(new SolidColorBrush(Colors.DarkGray)
//, new PropertyChangedCallback(OnForegroundChanged)
));
public Brush Foreground
{
get { return (Brush) GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public static readonly DependencyProperty MarginProperty = DependencyProperty
.Register("Margin", typeof (Thickness), typeof (HintBehavior)
, new FrameworkPropertyMetadata(new Thickness(4, 5, 0, 0)
//, new PropertyChangedCallback(OnMarginChanged)
));
public Thickness Margin
{
get { return (Thickness) GetValue(MarginProperty); }
set { SetValue(MarginProperty, value); }
}
private static ResourceDictionary _hintBehaviorResources;
public static ResourceDictionary HintBehaviorResources
{
get
{
if (_hintBehaviorResources == null)
{
var res = new ResourceDictionary
{
Source = new Uri("/Mayflower.Client.Core;component/Behaviors/HintBehaviorResources.xaml",
UriKind.RelativeOrAbsolute)
};
_hintBehaviorResources = res;
}
return _hintBehaviorResources;
}
}
protected override void OnAttached()
{
base.OnAttached();
var t = (ControlTemplate) HintBehaviorResources["HintBehaviorWrapper"];
AssociatedObject.Template = t;
AssociatedObject.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
AssociatedObject.Loaded -= OnLoaded;
var label = (Label) AssociatedObject.Template.FindName("PART_HintLabel", AssociatedObject);
label.DataContext = this;
//label.Content = "Hello...";
label.SetBinding(UIElement.VisibilityProperty, new Binding("Visibility") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(ContentControl.ContentProperty, new Binding("Hint") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(Control.ForegroundProperty, new Binding("Foreground") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(FrameworkElement.MarginProperty, new Binding("Margin") {Source = this, Mode = BindingMode.OneWay});
}
}
它用自己的模板包装目标,并向其添加一个标签:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="HintBehaviorWrapper" TargetType="{x:Type ContentControl}">
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" />
<Label x:Name="PART_HintLabel" IsHitTestVisible="False" Padding="0" />
</Grid>
</ControlTemplate>
</ResourceDictionary>
要使用它,只需将其添加为一个行为并绑定你的值(在我的情况下,我将它添加在一个ControlTemplate中,因此绑定):
<ContentControl>
<i:Interaction.Behaviors>
<behaviors:HintBehavior Value="{Binding Property, RelativeSource={RelativeSource TemplatedParent}}"
Hint="{Binding Hint, RelativeSource={RelativeSource TemplatedParent}}" />
</i:Interaction.Behaviors>
<TextBox ... />
</ContentControl>
如果这是一个干净的解决方案,我希望得到反馈。它不需要静态字典,因此没有内存泄漏。
我看到了John Myczek的解决方案,以及它关于ComboBox和PasswordBox兼容性的评论,所以我改进了John Myczek的解决方案,它是:
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 TextBox || d is PasswordBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
}
else if (d is ComboBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
(d as ComboBox).SelectionChanged += new SelectionChangedEventHandler(SelectionChanged);
}
else if (d is ItemsControl)
{
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);
}
}
/// <summary>
/// Event handler for the selection 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 SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
#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))
{
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).SelectedItem == null;
//return (c as ComboBox).Text == string.Empty;
}
else if (c is TextBoxBase)
{
return (c as TextBox).Text == string.Empty;
}
else if (c is PasswordBox)
{
return (c as PasswordBox).Password == string.Empty;
}
else if (c is ItemsControl)
{
return (c as ItemsControl).Items.Count == 0;
}
else
{
return false;
}
}
#endregion
}
现在,一个组合框也可以编辑,密码框也可以添加水印。 别忘了用上面JoanComasFdz的评论来解决保证金问题。
当然,这都是约翰·麦切克的功劳。
最简单的方法水印的文本框
<Window.Resources>
<Style x:Key="MyWaterMarkStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border Background="White" BorderBrush="#FF7D8683" BorderThickness="1"/>
<ScrollViewer x:Name="PART_ContentHost" Margin="5,0,0,0" VerticalAlignment="Center" />
<Label Margin="5,0,0,0" x:Name="WaterMarkLabel" Content="{TemplateBinding Tag}" VerticalAlignment="Center"
Visibility="Collapsed" Foreground="Gray" FontFamily="Arial"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="WaterMarkLabel" Value="Visible"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="DimGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
并添加文本框StaticResource样式
<TextBox
Style="{StaticResource MyWaterMarkStyle}"
Tag="Search Category"
Grid.Row="0"
Text="{Binding CategorySearch,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
TextSearch.Text="Search Category"
>
推荐文章
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头
- 如果我使用OWIN Startup.cs类并将所有配置移动到那里,我是否需要一个Global.asax.cs文件?
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 从另一个列表id中排序一个列表
- 等待一个无效的异步方法
- 无法加载文件或程序集…参数不正确
- c#中枚举中的方法
- 如何从字符串中删除新的行字符?
- 如何设置一个默认值与Html.TextBoxFor?
- 检查属性是否有属性
- 格式化XML字符串以打印友好的XML字符串
- 返回内容与IHttpActionResult非ok响应