WPF مائية PasswordBox من مربع نص العلامة المائية
-
05-07-2019 - |
سؤال
أنا باستخدام علامة مائية النص كما في علامة مائية النص في WPF
<Grid Grid.Row="0" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
<TextBlock Margin="5,2" Text="This prompt dissappears as you type..." Foreground="{StaticResource brushWatermarkForeground}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
</Grid>
كيف يمكنني تطبيق هذا PasswordBox?
المحلول
النهج العام هو نفسه:تكتب التحكم المخصصة نمط عرض العلامة المائية كلما مربع كلمة المرور فارغة.المشكلة الوحيدة هنا هي أن PasswordBox.كلمة المرور الملكية ليست تبعية الملكية, و لا يمكنك استخدامه في الزناد.أيضا PasswordBox مختومة ، بحيث لا يمكن تجاوز هذا الإخطار السلوك.ولكن يمكنك استخدام الخصائص المرفقة هنا.التعليمة البرمجية التالية يوضح كيفية.
XAML
<Window x:Class="WpfTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfTest="clr-namespace:WpfTest"
Title="Password Box Sample" Height="300" Width="300">
<Window.Resources>
<Style x:Key="{x:Type PasswordBox}"
TargetType="{x:Type PasswordBox}">
<Setter Property="WpfTest:PasswordBoxMonitor.IsMonitoring"
Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="true">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<TextBlock Text="Please enter your password"
Margin="4, 2, 0, 0"
Foreground="Gray"
Visibility="Collapsed"
Name="txtPrompt" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="WpfTest:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<PasswordBox VerticalAlignment="Top"/>
</Grid>
</Window>
C#
using System.Windows;
using System.Windows.Controls;
namespace WpfTest
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
public class PasswordBoxMonitor : DependencyObject
{
public static bool GetIsMonitoring(DependencyObject obj)
{
return (bool)obj.GetValue(IsMonitoringProperty);
}
public static void SetIsMonitoring(DependencyObject obj, bool value)
{
obj.SetValue(IsMonitoringProperty, value);
}
public static readonly DependencyProperty IsMonitoringProperty =
DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxMonitor), new UIPropertyMetadata(false, OnIsMonitoringChanged));
public static int GetPasswordLength(DependencyObject obj)
{
return (int)obj.GetValue(PasswordLengthProperty);
}
public static void SetPasswordLength(DependencyObject obj, int value)
{
obj.SetValue(PasswordLengthProperty, value);
}
public static readonly DependencyProperty PasswordLengthProperty =
DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxMonitor), new UIPropertyMetadata(0));
private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var pb = d as PasswordBox;
if (pb == null)
{
return;
}
if ((bool) e.NewValue)
{
pb.PasswordChanged += PasswordChanged;
}
else
{
pb.PasswordChanged -= PasswordChanged;
}
}
static void PasswordChanged(object sender, RoutedEventArgs e)
{
var pb = sender as PasswordBox;
if (pb == null)
{
return;
}
SetPasswordLength(pb, pb.Password.Length);
}
}
}
من فضلك لاحظ PasswordBoxMonitor في XAML كود.
نصائح أخرى
ويمكنك إظهار / إخفاء الخلفية من نفسك بدلا من استخدام المشغلات:
وXAML:
<PasswordBox x:Name="passwordBox" PasswordChanged="passwordChanged"
Background="{StaticResource PasswordHint}" />
ورمز وراء:
// helper to hide watermark hint in password field
private void passwordChanged(object sender, RoutedEventArgs e)
{
if (passwordBox.Password.Length == 0)
passwordBox.Background.Opacity = 1;
else
passwordBox.Background.Opacity = 0;
}
ويمكنك استخدام توجهي للسلوك مائية. كل ما عليك القيام به هو نسخ ولصق TextBoxWatermarkBehavior
والتغيير Behavior<TextBox>
إلى Behavior<PasswordBox>
.
ويمكنك العثور على مشروع تجريبي هنا أ >
blindmeis هو خير . لPasswordBox الطبقة ستكون على النحو التالي.
public class PasswordBoxWatermarkBehavior : System.Windows.Interactivity.Behavior<PasswordBox>
{
private TextBlockAdorner adorner;
private WeakPropertyChangeNotifier notifier;
#region DependencyProperty's
public static readonly DependencyProperty LabelProperty =
DependencyProperty.RegisterAttached("Label", typeof(string), typeof(PasswordBoxWatermarkBehavior));
public string Label
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty LabelStyleProperty =
DependencyProperty.RegisterAttached("LabelStyle", typeof(Style), typeof(PasswordBoxWatermarkBehavior));
public Style LabelStyle
{
get { return (Style)GetValue(LabelStyleProperty); }
set { SetValue(LabelStyleProperty, value); }
}
#endregion
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Loaded += this.AssociatedObjectLoaded;
this.AssociatedObject.PasswordChanged += AssociatedObjectPasswordChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.Loaded -= this.AssociatedObjectLoaded;
this.AssociatedObject.PasswordChanged -= this.AssociatedObjectPasswordChanged;
this.notifier = null;
}
private void AssociatedObjectPasswordChanged(object sender, RoutedEventArgs e)
{
this.UpdateAdorner();
}
private void AssociatedObjectLoaded(object sender, System.Windows.RoutedEventArgs e)
{
this.adorner = new TextBlockAdorner(this.AssociatedObject, this.Label, this.LabelStyle);
this.UpdateAdorner();
//AddValueChanged for IsFocused in a weak manner
this.notifier = new WeakPropertyChangeNotifier(this.AssociatedObject, UIElement.IsFocusedProperty);
this.notifier.ValueChanged += new EventHandler(this.UpdateAdorner);
}
private void UpdateAdorner(object sender, EventArgs e)
{
this.UpdateAdorner();
}
private void UpdateAdorner()
{
if (!String.IsNullOrEmpty(this.AssociatedObject.Password) || this.AssociatedObject.IsFocused)
{
// Hide the Watermark Label if the adorner layer is visible
this.AssociatedObject.TryRemoveAdorners<TextBlockAdorner>();
}
else
{
// Show the Watermark Label if the adorner layer is visible
this.AssociatedObject.TryAddAdorner<TextBlockAdorner>(adorner);
}
}
}