我怎么能把一些文本放入一个文本框,这将被自动删除时,用户键入的东西在它?
当前回答
<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" />
这可以帮助检查您的代码。当应用到密码框时,它将显示密码,当用户输入时,它将消失。
其他回答
我不敢相信居然没有人发布Xceed的WPF扩展工具包——WatermarkTextBox。它工作得很好,并且是开源的,如果你想定制的话。
编辑:虽然仍然是开源的,但这个库现在只对非商业用途免费,请参阅价格和许可证。
这里有一个最简单的解决方案:
<Grid>
<Label Content="Placeholder text" VerticalAlignment="Center" Margin="10">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Expression}" Value="">
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<TextBox HorizontalAlignment="Stretch" Margin="5" Background="Transparent"
Text="{Binding Expression, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Padding="5">
</TextBox>
</Grid>
这是一个透明背景覆盖标签的文本框。标签的灰色文本通过数据触发器变成透明的,只要绑定的文本不是空字符串就会触发该触发器。
我决定通过一个行为来解决这个问题。它使用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>
如果这是一个干净的解决方案,我希望得到反馈。它不需要静态字典,因此没有内存泄漏。
我的解决办法很简单。
在我的登录窗口。xaml是这样的。
<DockPanel HorizontalAlignment="Center" VerticalAlignment="Center" Height="80" Width="300" LastChildFill="True">
<Button Margin="5,0,0,0" Click="login_Click" DockPanel.Dock="Right" VerticalAlignment="Center" ToolTip="Login to system">
Login
</Button>
<StackPanel>
<TextBox x:Name="userNameWatermarked" Height="25" Foreground="Gray" Text="UserName" GotFocus="userNameWatermarked_GotFocus"></TextBox>
<TextBox x:Name="userName" Height="25" TextChanged="loginElement_TextChanged" Visibility="Collapsed" LostFocus="userName_LostFocus" ></TextBox>
<TextBox x:Name="passwordWatermarked" Height="25" Foreground="Gray" Text="Password" Margin="0,5,0,5" GotFocus="passwordWatermarked_GotFocus"></TextBox>
<PasswordBox x:Name="password" Height="25" PasswordChanged="password_PasswordChanged" KeyUp="password_KeyUp" LostFocus="password_LostFocus" Margin="0,5,0,5" Visibility="Collapsed"></PasswordBox>
<TextBlock x:Name="loginError" Visibility="Hidden" Foreground="Red" FontSize="12"></TextBlock>
</StackPanel>
</DockPanel>
代码是这样的。
private void userNameWatermarked_GotFocus(object sender, RoutedEventArgs e)
{
userNameWatermarked.Visibility = System.Windows.Visibility.Collapsed;
userName.Visibility = System.Windows.Visibility.Visible;
userName.Focus();
}
private void userName_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.userName.Text))
{
userName.Visibility = System.Windows.Visibility.Collapsed;
userNameWatermarked.Visibility = System.Windows.Visibility.Visible;
}
}
private void passwordWatermarked_GotFocus(object sender, RoutedEventArgs e)
{
passwordWatermarked.Visibility = System.Windows.Visibility.Collapsed;
password.Visibility = System.Windows.Visibility.Visible;
password.Focus();
}
private void password_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.password.Password))
{
password.Visibility = System.Windows.Visibility.Collapsed;
passwordWatermarked.Visibility = System.Windows.Visibility.Visible;
}
}
仅仅决定隐藏或显示水印文本框就足够了。虽然不漂亮,但工作得很好。
使用风格的简单解决方案:
<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
推荐文章
- 如何在c#中获得正确的时间戳
- Linq选择列表中存在的对象(A,B,C)
- c# .NET中的App.config是什么?如何使用它?
- c#:如何获得一个字符串的第一个字符?
- String类中的什么方法只返回前N个字符?
- 更好的方法将对象转换为int类型
- 我可以将c#字符串值转换为转义字符串文字吗?
- 在c#中转换char到int
- c#中朋友的对等物是什么?
- 关键字使用virtual+override vs. new
- 在ASP中选择Tag Helper。NET Core MVC
- 如何在没有任何错误或警告的情况下找到构建失败的原因
- 跨线程操作无效:控件“textBox1”从创建它的线程以外的线程访问
- 否ConcurrentList<T>在。net 4.0?
- 在c#中解析字符串为日期时间