2021年2月8日星期一

WPF中使用附加属性解决PasswordBox的数据绑定问题

WPF 中使用附加属性解决 PasswordBox 的数据绑定问题

1、前言

在 WPF 开发中 View 中的数据展示我们常通过 Binding 进行绑定。但是,使用 Binding 有一个前提:绑定的目标只能是依赖属性。 而 PasswordBox 控件中的 Password 并不是一个依赖属性,所以我们在使用 Password 时无法直接进行数据绑定。为了解决这个问题,我们就需要自己定义依赖属性。标题中的 "附加属性" 是依赖属性的一种特殊形式。

2、实现步骤

注:附加属性的定义方式:在 Visual Studio 中输入 propa ,然后按下两次 Tab 键即可。

2.1、定义一个 LoginPasswordBoxHelper 类,并在页面 xaml 代码中添加命名空间,该类用于辅助解决数据绑定问题。

2.2、在类中添加用于绑定的 Password 属性

public static class LoginPasswordBoxHelper{ public static string GetPassword(DependencyObject obj) {  return (string)obj.GetValue(PasswordProperty); } public static void SetPassword(DependencyObject obj, string value) {  obj.SetValue(PasswordProperty, value); } public static readonly DependencyProperty PasswordProperty =  DependencyProperty.RegisterAttached("Password", typeof(string), typeof(LoginPasswordBoxHelper), new PropertyMetadata("")); }

这个时候就可以在页面的 xaml 中的 PasswordBox 中添加如下数据绑定了:

<PasswordBox Width="200" Height="30"   vm:LoginPasswordBoxHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

但是,这时候只是提供了一个属性给 PasswordBox 用于 Binding,输入内容后数据没有任何更改效果。

因为当在 PasswordBox 中填写密码时,没有启动对应的事件将密码 Changed 到后端 ViewModel 中的 Password 属性

这时就需要再建一个附加属性 IsPasswordBindingEnable,用于给 PasswordBox 的更改添加事件,并在事件中更改到 后端 ViewModel 中的 Password 属性。

2.3、添加附加属性 IsPasswordBindingEnable,用于给 PasswordBox 的添加更改事件

当 IsPasswordBindingEnable="True" 时,给 PasswordBox 的 PasswordChanged 事件添加处理程序PasswordBoxPasswordChanged;

PasswordBoxPasswordChanged 作用:当页面中 PasswordBox 输入的值发生改变时,通过 SetPassword 完成数据更改,从而实现完整的数据绑定功能。

<PasswordBox Width="200" Height="30"    vm:LoginPasswordBoxHelper.IsPasswordBindingEnable="True"    vm:LoginPasswordBoxHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
public static bool GetIsPasswordBindingEnable(DependencyObject obj){ return (bool)obj.GetValue(IsPasswordBindingEnableProperty);}public static void SetIsPasswordBindingEnable(DependencyObject obj, bool value){ obj.SetValue(IsPasswordBindingEnableProperty, value);}public static readonly DependencyProperty IsPasswordBindingEnableProperty = DependencyProperty.RegisterAttached("IsPasswordBindingEnable", typeof(bool), typeof(LoginPasswordBoxHelper),          new FrameworkPropertyMetadata(OnIsPasswordBindingEnabledChanged));private static void OnIsPasswordBindingEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e){ var passwordBox = obj as PasswordBox; if (passwordBox != null) {  passwordBox.PasswordChanged -= PasswordBoxPasswordChanged;  if ((bool)e.NewValue)  {   passwordBox.PasswordChanged += PasswordBoxPasswordChanged;  } }}static void PasswordBoxPasswordChanged(object sender, RoutedEventArgs e){ var passwordBox = (PasswordBox)sender; if (!String.Equals(GetPassword(passwordBox), passwordBox.Password)) {  SetPassword(passwordBox, passwordBox.Password); }}

3、完整代码

3.1、页面代码

Login.xaml

<Window x: 

Login.xaml.cs

using PasswordBoxDemo.ViewModel;using System.Windows;namespace PasswordBoxDemo{ public partial class Login : Window {  private MainViewModel resource;  public Login()  {   InitializeComponent();   resource = new MainViewModel();   this.DataContext = resource;  } }}

3.2、数据绑定辅助类 LoginPasswordBoxHelper

using System;using System.Windows;using System.Windows.Controls;namespace PasswordBoxDemo.ViewModel{ public static class LoginPasswordBoxHelper {  public static string GetPassword(DependencyObject obj)  {   return (string)obj.GetValue(PasswordProperty);  }  public static void SetPassword(DependencyObject obj, string value)  {   obj.SetValue(PasswordProperty, value);  }    public static readonly DependencyProperty PasswordProperty =   DependencyProperty.RegisterAttached("Password", typeof(string), typeof(LoginPasswordBoxHelper), new PropertyMetadata(""));  public static bool GetIsPasswordBindingEnable(DependencyObject obj)  {   return (bool)obj.GetValue(IsPasswordBindingEnableProperty);  }  public static void SetIsPasswordBindingEnable(DependencyObject obj, bool value)  {   obj.SetValue(IsPasswordBindingEnableProperty, value);  }    public static readonly DependencyProperty IsPasswordBindingEnableProperty =   DependencyProperty.RegisterAttached("IsPasswordBindingEnable", typeof(bool), typeof(LoginPasswordBoxHelper),    new FrameworkPropertyMetadata(OnIsPasswordBindingEnabledChanged));  private static void OnIsPasswordBindingEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)  {   var passwordBox = obj as PasswordBox;   if (passwordBox != null)   {    passwordBox.PasswordChanged -= PasswordBoxPasswordChanged;    if ((bool)e.NewValue)    {     passwordBox.PasswordChanged += PasswordBoxPasswordChanged;    }   }  }  static void PasswordBoxPasswordChanged(object sender, RoutedEventArgs e)  {   var passwordBox = (PasswordBox)sender;   if (!String.Equals(GetPassword(passwordBox), passwordBox.Password))   {    SetPassword(passwordBox, passwordBox.Password);   }  } }}

3.3、其它代码

ViewModel:

using GalaSoft.MvvmLight;namespace PasswordBoxDemo.ViewModel{ public class MainViewModel : ViewModelBase {  public MainViewModel()  {  }  private string userName;  public string UserName  {   get { return userName; }   set { userName = value; RaisePropertyChanged(); }  }  private string password;  public string Password  {   get { return password; }   set { password = value; RaisePropertyChanged(); }  } }}

4、附加功能:输入框添加水印

实现水印添加也可以用类似上述的方法实现,具体步骤如下:

4.1、在 LoginPasswordBoxHelper 类中添加附加属性 ShowWaterMark,用与切换水印展示状态;

public static bool GetShowWaterMark(DependencyObject obj){ return (bool)obj.GetValue(ShowWaterMarkProperty);}public static void SetShowWaterMark(DependencyObject obj, bool value){ obj.SetValue(ShowWaterMarkProperty, value);}/// <summary>/// 控制水印显示/// </summary>public static readonly DependencyProperty ShowWaterMarkProperty = DependencyProperty.RegisterAttached("ShowWaterMark", typeof(bool), typeof(LoginPasswordBoxHelper),          new FrameworkPropertyMetadata(true, OnShowWaterMarkChanged));private static void OnShowWaterMarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){}

4.2、自定义水印展示样式

<Window.Resources> <Style x:Key="textbox" TargetType="{x:Type TextBox}">  <Setter Property="Padding" Value="2,5,0,0"/>  <Setter Property="FontSize" Value="14"/>  <Style.Triggers>   <Trigger Property="Text" Value="">    <Setter Property="Background">     <Setter.Value>      <VisualBrush AlignmentX="Left" AlignmentY="Center" Stretch="None">       <VisualBrush.Visual>        <TextBlock Padding="5,3,0,0" Background="Transparent" Foreground="Silver" FontSize="14" Text="请输入用户名"></TextBlock>       </VisualBrush.Visual>      </VisualBrush>     </Setter.Value>    </Setter>   </Trigger>  </Style.Triggers> </Style> <Style x:Key="password" TargetType="{x:Type PasswordBox}">  <Setter Property="Padding" Value="2,5,0,0"/>  <Setter Property="FontSize" Value="14"/>  <Setter Property="Template">   <Setter.Value>    <ControlTemplate TargetType="{x:Type PasswordBox}">     <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"       BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true">      <Grid>       <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>       <StackPanel Orientation="Horizontal" Visibility="Visible" Name="myWaterMark">        <TextBlock Padding="3" Background="Transparent" Foreground="Silver" FontSize="14"           Text="请输入密码"/>       </StackPanel>      </Grid>     </Border>     <ControlTemplate.Triggers>      <Trigger Property="IsEnabled" Value="false">       <Setter Property="Visibility" TargetName="myWaterMark" Value="Collapsed"/>      </Trigger>      <Trigger Property="vm:LoginPasswordBoxHelper.ShowWaterMark" Value="False">       <Setter Property="Visibility" TargetName="myWaterMark" Value="Collapsed"/>      </Trigger>     </ControlTemplate.Triggers>    </ControlTemplate>   </Setter.Value>  </Setter> </Style></Window.Resources>

5、效果展示

image-20210207193228330









原文转载:http://www.shaoqun.com/a/536576.html

跨境电商:https://www.ikjzd.com/

net-a-porter:https://www.ikjzd.com/w/2132

克雷格:https://www.ikjzd.com/w/194


WPF中使用附加属性解决PasswordBox的数据绑定问题1、前言在WPF开发中View中的数据展示我们常通过Binding进行绑定。但是,使用Binding有一个前提:绑定的目标只能是依赖属性。而PasswordBox控件中的Password并不是一个依赖属性,所以我们在使用Password时无法直接进行数据绑定。为了解决这个问题,我们就需要自己定义依赖属性。标题中的"附加属性"是依赖属性的一
贝贝官网:贝贝官网
FEN:FEN
个人卖家如何注册eBay?2018 eBay个人账号开店注册流程:个人卖家如何注册eBay?2018 eBay个人账号开店注册流程
15份亚马逊常用表格:15份亚马逊常用表格
码!如何用电子书来获取亚马逊取客户邮件【详解】:码!如何用电子书来获取亚马逊取客户邮件【详解】