C# 密码箱中的水印
我实现了以下转换器和代码,目的是创建某种水印。此代码适用于C# 密码箱中的水印,c#,wpf,mvvm,converter,watermark,C#,Wpf,Mvvm,Converter,Watermark,我实现了以下转换器和代码,目的是创建某种水印。此代码适用于TextBlock+TextBox,但不适用于TextBlock+PasswordBox。你知道为什么这个转换器不工作吗 XAML <Helpers:HintConverter x:Key="hint" /> <TextBlock Height="30" Text=" password" Foreground="LightGray" Margin="274,26
TextBlock+TextBox
,但不适用于TextBlock+PasswordBox
。你知道为什么这个转换器不工作吗
XAML
<Helpers:HintConverter x:Key="hint" />
<TextBlock Height="30" Text=" password" Foreground="LightGray" Margin="274,264,278,306" Width="248">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource hint}">
<Binding ElementName="txtPassword" Path="Text.IsEmpty" />
<Binding ElementName="txtPassword" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<PasswordBox PasswordChanged="PasswordBox_PasswordChanged" Name="txtPassword" BorderThickness="2" Height="30" Margin="273,264,275,306" Background="Transparent">
<PasswordBox.BorderBrush>
<LinearGradientBrush EndPoint="1,1" StartPoint="1,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="White" Offset="0.75" />
<GradientStop Color="Green" Offset="0.75" />
<GradientStop Color="#FF0D9ECD" Offset="1" />
</LinearGradientBrush>
</PasswordBox.BorderBrush>
</PasswordBox>
PasswordBox
没有Text
属性,它有Password
和SecurePassword
属性,这些属性不是依赖属性-因此您不会收到任何更改通知
您可以定义一个附加属性,该属性订阅PasswordChanged
事件并绑定到该事件:
public static class PasswordBoxExtensions
{
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.RegisterAttached(
"IsActive", typeof(bool), typeof(PasswordBoxExtensions),
new FrameworkPropertyMetadata(OnIsActiveChanged));
private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var passwordBox = d as PasswordBox;
if (passwordBox == null) return;
passwordBox.PasswordChanged -= OnPasswordChanged;
if ((bool)e.NewValue)
{
SetIsPasswordEmpty(passwordBox);
passwordBox.PasswordChanged += OnPasswordChanged;
}
}
private static void OnPasswordChanged(object sender, RoutedEventArgs e)
{
SetIsPasswordEmpty((PasswordBox)sender);
}
public static void SetIsActive(PasswordBox element, bool value)
{
element.SetValue(IsActiveProperty, value);
}
public static bool GetIsActive(PasswordBox element)
{
return (bool)element.GetValue(IsActiveProperty);
}
public static readonly DependencyPropertyKey IsPasswordEmptyPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(
"IsPasswordEmpty", typeof(bool), typeof(PasswordBoxExtensions),
new FrameworkPropertyMetadata());
public static readonly DependencyProperty IsPasswordEmptyProperty =
IsPasswordEmptyPropertyKey.DependencyProperty;
private static void SetIsPasswordEmpty(PasswordBox element)
{
element.SetValue(IsPasswordEmptyPropertyKey, element.SecurePassword.Length == 0);
}
public static bool GetIsPasswordEmpty(PasswordBox element)
{
return (bool)element.GetValue(IsPasswordEmptyProperty);
}
}
用法:
<PasswordBox Name="txtPassword" app:PasswordBoxExtensions.IsActive="True" />
<Binding ElementName="txtPassword" Path="(app:PasswordBoxExtensions.IsPasswordEmpty)" />
我下一步做什么
XAML:
视图模型:
public string Password
{
get { return _password; }
set
{
_password = value;
IsPasswordWatermarkVisible = string.IsNullOrEmpty(_password);
}
}
public bool IsPasswordWatermarkVisible
{
get { return _isPasswordWatermarkVisible; }
set
{
if (value.Equals(_isPasswordWatermarkVisible)) return;
_isPasswordWatermarkVisible = value;
OnPropertyChanged();
}
}
请尝试删除
Background=“Transparent”
@Venky不工作:/谢谢您的回答,因此我在实现中遇到了一些问题。我在Resources文件夹中创建了这个类,并使用如下方式:Resources:PasswordBoxExtensions.IsActive=“True”但不知何故它无法识别。您需要在XAML的根目录下添加一个xmlns
,例如:xmlns:Resources=“clr namespace:YourNamespace.Resources”
(用应用程序的命名空间替换YourNamespace
。已经这样做了。xmlns:Resources=“clr namespace:Wpfv0.Resources”仍然没有:xIs它都在同一个程序集中吗?在包含公共静态类PasswordBoxExtensions的文件中是否有namespace Wpfv0.Resources{
{
?不再显示错误,但绑定仍有问题。是否在密码框中?
<PasswordBox Name="PasswordBox"
PasswordChanged="PasswordBox_OnPasswordChanged"/>
<TextBlock Text="PASSWORD"
IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource WatermarkStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPasswordWatermarkVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
private MyViewModel ViewModel
{
get { return (MyViewModel) DataContext; }
}
private void PasswordBox_OnPasswordChanged(object sender, RoutedEventArgs e)
{
ViewModel.Password = PasswordBox.Password;
}
public string Password
{
get { return _password; }
set
{
_password = value;
IsPasswordWatermarkVisible = string.IsNullOrEmpty(_password);
}
}
public bool IsPasswordWatermarkVisible
{
get { return _isPasswordWatermarkVisible; }
set
{
if (value.Equals(_isPasswordWatermarkVisible)) return;
_isPasswordWatermarkVisible = value;
OnPropertyChanged();
}
}