WPF 使用附加属性实现 PasswordBox 控件 Password 同步到 ViewModel

参考

环境

软件/系统 版本 说明
Windows windows 10 专业版 22H2 64 位操作系统, 基于 x64 的处理器
Microsoft Visual Studio Community 2022 (64 位) - Current 版本 17.14.9
Prism Template Pack 2.4.1 Microsoft Visual Studio 扩展
.NET 6
Prism.Unity 8.1.97 nuget依赖库(使用 Prism Template Pack 创建项目时选择的容器,使用模板创建的项目自动安装)
MaterialDesignThemes 5.2.1 nuget依赖库

正文

步骤

  1. 实现 PasswordBoxHelper.cs
  2. Login.xaml 页面附加属性类的命名空间 xmlns:helper="clr-namespace:WPFNetConnect.Helper"
  3. 在控件中使用
    <PasswordBox
    	x:Name="LoginPasswordBox"
    	helper:PasswordBoxHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    	Style="{StaticResource LoginPasswordBox}" />
    

主要代码

  1. PasswordBoxHelper.cs
    using System.Windows;
    using System.Windows.Controls;
    
    namespace WPFNetConnect.Helper
    {
    	public static class PasswordBoxHelper
    	{
    		public static string GetPassword(DependencyObject obj) => (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(PasswordBoxHelper),
    				new FrameworkPropertyMetadata(OnPasswordPropertyChangedCallback));
    
    		private static void OnPasswordPropertyChangedCallback(
    			DependencyObject d, DependencyPropertyChangedEventArgs e)
    		{
    			if (d is PasswordBox passwordBox)
    			{
    				passwordBox.PasswordChanged -= PasswordBox_PasswordChanged;
    				passwordBox.PasswordChanged += PasswordBox_PasswordChanged;
    			}
    		}
    
    		private static void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
    		{
    			if (sender is PasswordBox passwordBox)
    			{
    				SetPassword(passwordBox, passwordBox.Password);
    			}
    		}
    	}
    }
    
  2. Login.xaml
    <Window
    	x:Class="WPFNetConnect.Views.Login"
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	xmlns:helper="clr-namespace:WPFNetConnect.Helper"
    	xmlns:prism="http://prismlibrary.com/"
    	Title="{Binding Title}"
    	Width="1280"
    	Height="800"
    	prism:ViewModelLocator.AutoWireViewModel="True"
    	WindowStartupLocation="CenterScreen">
    	<Window.Resources>
    		<ResourceDictionary>
    			<!--  单独引入外部样式  -->
    			<ResourceDictionary.MergedDictionaries>
    				<ResourceDictionary Source="/Styles/LoginStyle.xaml" />
    			</ResourceDictionary.MergedDictionaries>
    		</ResourceDictionary>
    	</Window.Resources>
    	<Grid>
    		<Grid.ColumnDefinitions>
    			<ColumnDefinition Width="512" />
    			<ColumnDefinition />
    		</Grid.ColumnDefinitions>
    		<Image Grid.Column="0" Style="{StaticResource LoginLeft}" />
    		<StackPanel Grid.Column="1" Style="{StaticResource LoginRight}">
    			<Label Style="{StaticResource LoginTitle}">欢迎回来</Label>
    			<Label Style="{StaticResource LoginDesc}">登陆到您的账户</Label>
    			<Label Style="{StaticResource LoginAccountTitle}">用户名</Label>
    			<TextBox
    				x:Name="LoginAccountTextBox"
    				Style="{StaticResource LoginAccountTextBox}"
    				Text="{Binding Path=Account}" />
    			<Label Style="{StaticResource LoginPasswordTitle}">密码</Label>
    			<PasswordBox
    				x:Name="LoginPasswordBox"
    				helper:PasswordBoxHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    				Style="{StaticResource LoginPasswordBox}" />
    			<Button Command="{Binding SubmitBtnCommand}" Style="{StaticResource LoginSubmitButton}">
    				登录
    			</Button>
    			<Label Style="{StaticResource LoginErrorTip}">无法登录?联系管理员</Label>
    		</StackPanel>
    		<Label
    			Grid.Column="1"
    			Content="NetConnect v1.0.5"
    			Style="{StaticResource LoginVersion}" />
    	</Grid>
    </Window>
    
posted @ 2025-07-17 22:15  夏秋初  阅读(35)  评论(0)    收藏  举报