Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 密码箱中的水印_C#_Wpf_Mvvm_Converter_Watermark - Fatal编程技术网

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();
        }
    }