【发布时间】:2013-07-10 12:41:38
【问题描述】:
我需要 WatermarkPasswordBox 控件,但 Winrt 中没有。也许我们可以将 Watermark 属性添加到 PasswordBox。有人能做到吗?
谢谢
【问题讨论】:
标签: textbox windows-runtime watermark maskedtextbox passwordbox
我需要 WatermarkPasswordBox 控件,但 Winrt 中没有。也许我们可以将 Watermark 属性添加到 PasswordBox。有人能做到吗?
谢谢
【问题讨论】:
标签: textbox windows-runtime watermark maskedtextbox passwordbox
水印的目的是在控件背后传达信息。在本演示中,水印在您开始输入文本后也会消失,因此它们更像是一个“提示”字段,告诉您预期的内容。
为了实现这一点,我们求助于常规的 WPF 解决方案提供商,即 AttachedProperty。 AttachedProperties 允许您向任何控件添加额外的属性。您还可以将其扩展为 Attachedbehaviour,让控件对属性的更改做出反应。
在本例中,我们使用了两个附加属性。第一个“WaterrmarkProperty”取水印值并初始化控件:
public static string GetWatermark(DependencyObject obj)
{
return (string)obj.GetValue(WatermarkProperty);
}
public static void SetWatermark(DependencyObject obj, string value)
{
obj.SetValue(WatermarkProperty, value);
}
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.RegisterAttached("Watermark", typeof(string), typeof(TextBoxHelper), new UIPropertyMetadata(null, WatermarkChanged));
第二个附加属性是通知框内是否有值,模板绑定并隐藏或显示水印。
public static bool GetShowWatermark(DependencyObject obj)
{
return (bool)obj.GetValue(ShowWatermarkProperty);
}
public static void SetShowWatermark(DependencyObject obj, bool value)
{
obj.SetValue(ShowWatermarkProperty, value);
}
public static readonly DependencyProperty ShowWatermarkProperty =
DependencyProperty.RegisterAttached("ShowWatermark", typeof(bool), typeof(TextBoxHelper), new UIPropertyMetadata(false));
对于TextBoxHelper,每当文本发生变化时,水印就会显示或隐藏,如下所示:
private static void CheckShowWatermark(TextBox box)
{
box.SetValue(TextBoxHelper.ShowWatermarkProperty, box.Text == string.Empty);
}
这由 ControlTemplate 控制:
<ControlTemplate x:Key="WatermarkedTextBoxTemplate" TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<Grid>
<TextBlock Text="{Binding Path=(local:TextBoxHelper.Watermark), RelativeSource={RelativeSource TemplatedParent}}" Opacity=".5" FontWeight="Bold" Visibility="{Binding (local:TextBoxHelper.ShowWatermark), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}" />
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
来源:http://code.msdn.microsoft.com/windowsdesktop/Watermarked-TextBox-and-444ebdec
【讨论】:
在 Windows 8.0 中,您可以使用来自 WinRT XAML 工具包的WatermarkPasswordBox,您可以从here 获得该工具包。它为您提供了一个 Watermark 属性来将任何 UI 元素(Shape、Image 等)设置为水印或采用文本的 WatermarkText 属性和采用 TextBlock 的 WatermarkTextStyle 属性设置文本样式。
在 Windows 8.1 中,您可以使用相同的属性或使用新的 PlaceholderText 属性。
随意从库中删除和修改WatermarkPasswordBox 控件的代码,并在您的应用程序中使用它。它是麻省理工学院许可的。不需要学分。只需获取 .cs 和 .xaml 文件并将 .xaml 资源字典包含在您的 Themes/Generic.xaml 中,如下所示:
<ResourceDictionary
Source="ms-appx:///YourControlsLibraryNamefNotInMainApp/RelativeDirectoryPathOfTheFile/WatermarkPasswordBox.xaml" />
【讨论】:
更新 1
如果您不想使用 3rd 方 DLL,请将这两个方法添加到 PasswordBoxBehavior.cs 文件中。
using System.Reflection;
public static T FindVisualChildByName<T>(this DependencyObject fe, string name) where T : DependencyObject
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(fe); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(fe, i);
string a = child.GetValue(FrameworkElement.NameProperty) as string;
if (a == name)
{
return child as T;
}
T t = FindVisualChildByName<T>(child, name);
if (t != null)
{
return t;
}
}
return default(T);
}
public static T FindVisualParent<T>(this DependencyObject fe) where T : DependencyObject
{
for (fe = VisualTreeHelper.GetParent(fe); fe != null; fe = VisualTreeHelper.GetParent(fe))
{
T t = fe as T;
if (t != null)
{
return t;
}
}
return default(T);
}
这是来自 JulMar 的大量博客
【讨论】:
<PasswordBox />中设置IsTabStop="False"。