如何实现WPF登陆界面的记住账号密码功能()

在这里插入图片描述
刚开始学编程。学了三个月了,学的C#和.net(貌似有点坑),公司应该是让做b/s,socket和数据库比较难,暂时不怎么会,对WPF花的时间比较多一些(毕竟可视化效果看起来比价有成就感)(WPF的课程案例貌似不多,加油)
新手菜鸟,大神勿喷。我觉得几个有趣的地方,左上角的【HIM是画的,因为这样缩放清晰度一样,刺激。

<Polygon Fill="DarkSlateGray" Stroke="DarkSlateGray" StrokeThickness="1" FillRule="EvenOdd" Points="5,5 67,5 62,13 25,13 25,47 62,47 67,55 5,55"/>

图片那个是把一个TabControl控件翻转了180°

<TabControl.RenderTransform>
                    <RotateTransform Angle="180"/>
                </TabControl.RenderTransform>

好了,接下来看如何记住账号密码功能。主要是两个文本框,一个是textbox,另一个是passwordbox,还有一个记住密码的勾选框

<TextBox Name="txt_UserName"  Text="{Binding Path=SaveLoginID}"
                HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="200" Height="40"></TextBox>
<PasswordBox Name="txt_PSW"  PasswordChar="*" 
                                 local:PasswortBoxHelper.Attach="True" local:PasswortBoxHelper.Password="{Binding Path=SaveLoginPSW,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                 HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40"></PasswordBox>
<CheckBox Name="LoginIDMemory"  IsChecked="{Binding Path=SaveUser}">记住密码</CheckBox>

可以将控件的值保存在窗口中,但是这样做之后缺乏灵活性,会将应用程序数据与UI界面混在一起,并不是一种好的设计。我们应该新建一个类,并将用户所做的选择保存在其中。
(1)新建一个类,将其命名为SaveOptions
(2)我们要记住CheckBox,TextBox,PasswordBox的值,输入以下代码

using System;

namespace DataEntity
{
    [Serializable]
    public class SaveOptions
    {
        private bool _SaveUser = false;
        public bool SaveUser
        {
            get { };
            set { };
        }

        private string _SaveLoginID;
        public string SaveLoginID
        {
            get { };
            set { };
        }

        private string _SaveLoginPSW;
        public string SaveLoginPSW
        {
            get { };
            set { };
        }
    } 
}

(3)返回代码隐藏文件(我的是 登陆.xaml.cs),添加一个private字段来保存saveOptions实例;并在构造函数中添加以下代码。

using System.Windows;
using System.IO;
using System.Xml.Serialization;

namespace CfyDWS
{
    /// <summary>
    /// 登录.xaml 的交互逻辑
    /// </summary>
    public partial class LoginWindow : Window
    {
        private SaveOptions saveOptions;

        public LoginWindow()
        {
            if (saveOptions == null)
            {
                //确定指定的文件是否存在
                if (File.Exists("SaveOptions.xml"))
                {
                    using (var stream = File.OpenRead("SaveOptions.xml"))
                    {
                        var serializer = new XmlSerializer(typeof(SaveOptions));
                        saveOptions = serializer.Deserialize(stream) as SaveOptions;
                    }
                }
                else
                    saveOptions = new SaveOptions();
            }
            InitializeComponent();
        }
}

接下来创建动态绑定
(4)在InitializeComponent();这一行之前加上一下代码:

DataContext = saveOptions;

(5)转到SaveOptions类,对其进行修改

using System;
using System.ComponentModel;

namespace DataEntity
{
    [Serializable]
    public class SaveOptions : INotifyPropertyChanged
    {
        private bool _SaveUser = false;
        public bool SaveUser
        {
            get { return _SaveUser; }
            set
            {
                _SaveUser = value;
                OnPropertyChanged(nameof(SaveUser));
            }
        }

        private string _SaveLoginID;
        public string SaveLoginID
        {
            get { return _SaveLoginID; }
            set
            {
                _SaveLoginID = value;
                OnPropertyChanged(nameof(SaveLoginID));
            }
        }

        private string _SaveLoginPSW;
        public string SaveLoginPSW
        {
            get { return _SaveLoginPSW; }
            set
            {
                _SaveLoginPSW = value;
                OnPropertyChanged(nameof(SaveLoginPSW));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

(6)返回登陆.xaml文件,选择CheckBox,然后添加IsChenk属性,如下所示:

IsChecked="{Binding Path=SaveUser}"

(7)同理绑定TextBoX控件的Text属性

Text="{Binding Path=SaveLoginID}"

(8)绑定PasswordBox的Password属性时会出现一个错误,PasswordBox的Password属性不是依赖项属性,无法绑定。
其原因是,出于安全考虑,对密码进行数据库不是一个很好的设计,因此应该避免。但是有时这种安全性是不必要的,那么不能绑定到Password属性就很麻烦了。在这种特殊情况下,您可以利用以下PasswordBoxHelper。代码如下

http://www.wpftutorial.net/PasswordBox.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace CfyDWS
{
    public static class PasswortBoxHelper
    {
        //通过调用PasswordHelper.Attach财产。附加财产PasswordHelper.Password提供PasswordBox控件的原始密码属性的可绑定副本。
        public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.RegisterAttached("Password",
        typeof(string), typeof(PasswortBoxHelper),
        new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));

        public static readonly DependencyProperty AttachProperty =
            DependencyProperty.RegisterAttached("Attach",
            typeof(bool), typeof(PasswortBoxHelper), new PropertyMetadata(false, Attach));

        private static readonly DependencyProperty IsUpdatingProperty =
           DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
           typeof(PasswortBoxHelper));


        public static void SetAttach(DependencyObject dp, bool value)
        {
            dp.SetValue(AttachProperty, value);
        }

        public static bool GetAttach(DependencyObject dp)
        {
            return (bool)dp.GetValue(AttachProperty);
        }

        public static string GetPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(PasswordProperty);
        }

        public static void SetPassword(DependencyObject dp, string value)
        {
            dp.SetValue(PasswordProperty, value);
        }

        private static bool GetIsUpdating(DependencyObject dp)
        {
            return (bool)dp.GetValue(IsUpdatingProperty);
        }

        private static void SetIsUpdating(DependencyObject dp, bool value)
        {
            dp.SetValue(IsUpdatingProperty, value);
        }

        private static void OnPasswordPropertyChanged(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            PasswordBox passwordBox = sender as PasswordBox;
            passwordBox.PasswordChanged -= PasswordChanged;

            if (!(bool)GetIsUpdating(passwordBox))
            {
                passwordBox.Password = (string)e.NewValue;
            }
            passwordBox.PasswordChanged += PasswordChanged;
        }

        private static void Attach(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            PasswordBox passwordBox = sender as PasswordBox;

            if (passwordBox == null)
                return;

            if ((bool)e.OldValue)
            {
                passwordBox.PasswordChanged -= PasswordChanged;
            }

            if ((bool)e.NewValue)
            {
                passwordBox.PasswordChanged += PasswordChanged;
            }
        }

        private static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox passwordBox = sender as PasswordBox;
            SetIsUpdating(passwordBox, true);
            SetPassword(passwordBox, passwordBox.Password);
            SetIsUpdating(passwordBox, false);
        }
    }
}

查看登陆.xaml窗口,看到有名称空间CfyDWS的引用,没有的话自己手动添加,要引用CfyDWS名称空间下的PasswordBoxHelper类的方法。

<Window x:Class="CfyDWS.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CfyDWS"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="登录窗口" Icon="image\昌恒图标.png" Height="780" Width="1460" ResizeMode="CanMinimize">

然后修改PasswordBox的属性

<PasswordBox Name="txt_PSW"  PasswordChar="*" 
                                 local:PasswortBoxHelper.Attach="True" local:PasswortBoxHelper.Password="{Binding Path=SaveLoginPSW, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></PasswordBox>

这里说下看到的另一个方法,用TextBox替换PasswordBox,然后用TextDecorations属性画小黑点装饰TextBox,这种感觉窗口大小最好固定吧。而且小圆点的大小不好把握,也可能是我这里学的差。

https://blog.csdn.net/SANYUNI/article/details/52775898

(9)我把保存选项放在登陆按钮上了
这里我是当按下确定时,假如账号密码不对,未勾选记住密码,则清空账号密码框,如果正确,则登录
这里主要看using()的那一段代码段

        private void btn_login_Click(object sender, RoutedEventArgs e)
        {
            SqlConnectionStringBuilder connbuilder = new SqlConnectionStringBuilder();
            connbuilder.DataSource = Environment.MachineName;                             //获取服务器名称,本机为Cheng-PC(data ource数据源,一般为机器名称或IP地址)
            connbuilder.IntegratedSecurity = true;                                        //登录方式,true为 Windows 身份验证
            connbuilder.InitialCatalog = "昌恒DWS系统";                                   //数据库名(Initial Catalog数据库或SQL Server实例的名称(与Database一样))

            SqlConnection conn = new SqlConnection(connbuilder.ConnectionString);         //创建一个SqlConnecting对象并且初始化连接字符串
            conn.Open();                                                                  //打开数据库连接
            string a = string.Format("select * from 账户管理 where login_ID='{0}' and login_PSW='{1}' ", txt_UserName.Text, txt_PSW.Password);   
                                                                                          //定义要执行的SQL语句(本处是查询语句)
            SqlCommand comm = new SqlCommand(a, conn);                                    //创建SqlCommand的实例对象(string a表示要查询的文本,SqlConnecting conn表示到SQL Server实例的连接)
            SqlDataReader dr = comm.ExecuteReader();                                      //ExecuteReader(),读取数据,生成一个SqlDataReader对象并返回
            if (txt_UserName.Text == "" || txt_PSW.Password == "") //判断输入是否为空
            {
                MessageBox.Show("请填写用户名和密码");
                using (var stream = File.Open("SaveOptions.xml", FileMode.Create))
                {
                    if (LoginIDMemory.IsChecked == false)
                    {
                        saveOptions.SaveLoginID = "";
                        saveOptions.SaveLoginPSW = "";
                    }
                    var serializer = new XmlSerializer(typeof(SaveOptions));
                    serializer.Serialize(stream, saveOptions);
                }
            }

            else
            {
                if (dr.Read())//判断是否存在用户输入的用户名和密码
                {
                    MessageBox.Show("登陆成功"); // 显示主窗口;
                    this.DialogResult = Convert.ToBoolean(1);
                    using (var stream = File.Open("SaveOptions.xml", FileMode.Create))
                    {
                        if (LoginIDMemory.IsChecked == false)
                        {
                            saveOptions.SaveLoginID = "";
                            saveOptions.SaveLoginPSW = "";
                        }
                        var serializer = new XmlSerializer(typeof(SaveOptions));
                        serializer.Serialize(stream, saveOptions);
                    }
                    conn.Close();                                                          //关闭数据库连接
                    this.Close();
                }

                else
                {
                    MessageBox.Show("用户名或密码有误");
                    using (var stream = File.Open("SaveOptions.xml", FileMode.Create))
                    {
                        if (LoginIDMemory.IsChecked == false)
                        {
                            saveOptions.SaveLoginID = "";
                            saveOptions.SaveLoginPSW = "";
                        }
                        var serializer = new XmlSerializer(typeof(SaveOptions));
                        serializer.Serialize(stream, saveOptions);
                    }
                    conn.Close();                                                          //关闭数据库连接
                }
            }
        }

这里的using代码段也可以写进一个void方法里,直接调用方法

using (var stream = File.Open("SaveOptions.xml", FileMode.Create))
                    {
                        if (LoginIDMemory.IsChecked == false)
                        {
                            saveOptions.SaveLoginID = "";
                            saveOptions.SaveLoginPSW = "";
                        }
                        var serializer = new XmlSerializer(typeof(SaveOptions));
                        serializer.Serialize(stream, saveOptions);
                    }
``

猜你喜欢

转载自blog.csdn.net/LTyyCFY/article/details/84168344