2012-05-25 10:55:32 cyxcw1 阅读数 2229
  • C#急速入门

    Unity开发,C#绝对是基础中的基础,课程针对纯小白而设计,各种语言细节在课程里均有涉猎,从原理到实战,从底层到算法,你想了解的C#,这里应有尽有,除了讲解,还有练习,你说棒不棒,哈哈,当然如果你是有其他语言基础的同学,课程依然会让你收货满满。来吧,我们进入正题。

    13893 人正在学习 去看看 张建飞
/// <summary>
        /// 保存用户
        /// </summary>
        public void SetUser()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(Application.StartupPath + "//user.xml");
            XmlNodeList userNodes = xmlDoc.SelectSingleNode("root").ChildNodes;
            foreach (XmlNode userNode in userNodes)
            {
                XmlNodeList idandpwd = userNode.ChildNodes;
                foreach (XmlNode idnode in idandpwd)
                {
                    if (idnode.InnerText == cmbUserName.Text)
                    {
                        idnode.NextSibling.InnerText = jnzp.DESEncrypt.Encrypt(txtPwd.Text, "duowanSG");
                        xmlDoc.Save(Application.StartupPath + "//user.xml");
                        return;
                    }
                }
            }

            XmlNode root = xmlDoc.SelectSingleNode("root");//查找<root>
            XmlElement user = xmlDoc.CreateElement("user");
            XmlElement id = xmlDoc.CreateElement("id");
            XmlElement pwd = xmlDoc.CreateElement("pwd");
            id.InnerText = cmbUserName.Text;
            user.AppendChild(id);
            if (checkBox1.Checked)
            {
                pwd.InnerText = jnzp.DESEncrypt.Encrypt(txtPwd.Text, "duowanSG");
            }
            else
            {
                pwd.InnerText = "";
            }
            user.AppendChild(pwd);
            root.AppendChild(user);//添加到<bookstore>节点中
            xmlDoc.Save(Application.StartupPath + "//user.xml");

        }
        /// <summary>
        /// 提取密码
        /// </summary>
        /// <param name="userId">账号</param>
        /// <returns></returns>
        public string GetPwd(string userId)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(Application.StartupPath + "//user.xml");
            XmlNodeList userNodes = xmlDoc.SelectSingleNode("root").ChildNodes;
            foreach (XmlNode user in userNodes)
            {
                XmlNodeList idandpwd = user.ChildNodes;
                foreach (XmlNode idnode in idandpwd)
                {
                    if (idnode.InnerText == cmbUserName.Text)
                    {
                        string pwd=idnode.NextSibling.InnerText;
                        if (pwd == "")
                        {
                            return "";
                        }
                        return jnzp.DESEncrypt.Decrypt(pwd, "duowanSG");
                    }
                }
            }
            return "";
        }


==============================XML格式======================
<?xml version="1.0" encoding="utf-8"?>
<root>
  <user>
    <id>abcdefg</id>
    <pwd>FA52C9C83C4ACD73</pwd>
  </user>
</root> 

============================================================
给你说下思路.
当登录时,记录下账号密码,然后向XML中插入节点(不会的话,自己去网上搜一下),首先需要判断当前XML用户是否有了,有的话修改密码就行,没有新建.
在上面程序中,有checkbox来做判断是否记录密码.
2018-03-06 20:58:46 hzgisme 阅读数 2052
  • C#急速入门

    Unity开发,C#绝对是基础中的基础,课程针对纯小白而设计,各种语言细节在课程里均有涉猎,从原理到实战,从底层到算法,你想了解的C#,这里应有尽有,除了讲解,还有练习,你说棒不棒,哈哈,当然如果你是有其他语言基础的同学,课程依然会让你收货满满。来吧,我们进入正题。

    13893 人正在学习 去看看 张建飞

简单的实现用户登录记住账号密码功能

用户类:

    /// <summary>
    /// 用户
    /// </summary>
    [Serializable]
    public class User : BaseEntity
    {
        public int Id { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        [Display(Name = "用户名")]
        [StringLength(32)]
        public string Name { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        [Display(Name = "性别")]
        [StringLength(32)]
        public string Gender { get; set; }

        /// <summary>
        /// 用户分组
        /// </summary>
        [Display(Name = "用户分组")]
        [StringLength(32)]
        public string Group { get; set; }

        /// <summary>
        /// 角色
        /// </summary>
        [Display(Name = "角色")]
        [StringLength(32)]
        public string Role { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        [Display(Name = "密码")]
        [StringLength(255)]
        public string Password { get; set; }

        /// <summary>
        /// 登录时间
        /// </summary>
        [Display(Name = "登录时间")]
        public DateTime? LoginDateTime { get; set; }
    }

序列化,所谓序列化就是把实体对象保存到存储媒介中,以便于再次启动程序时可以读取到保存的信息。我们利用这个特点,实现用户账号和密码记住功能。

首先对用户类对象进行序列化:在用户登录成功时,保存用户的信息到本地。

                    Stream s = File.Open("user.dat", FileMode.OpenOrCreate);
                    BinaryFormatter binaryFormatter = new BinaryFormatter();

                    binaryFormatter.Serialize(s, user);
                    s.Close();

这样就把User类的实例保存到文件user.dat中,以便在用户再次打开程序时,自动输入账号和密码信息。

当用户再次进入登录界面时,我们对user.dat中保存的用户信息串行化,也就是把保存的信息还原为一个User对象,然后我们就可以使用读取到的信息填充登录界面的用户名和密码,实现记住账号和密码功能。

读取信息代码如下:

            if (!File.Exists("user.dat"))
            {
                return;
            }

            Stream fs = File.Open("user.dat", FileMode.Open);
            if (fs == null || fs.Length == 0)
            {
                return;
            }

            BinaryFormatter bf = new BinaryFormatter();

            object o = bf.Deserialize(fs);

            if (o is User user)
            {
                UserNameTextBox.Text = user.Name;
                PasswordTextBox.Text = user.Password;
                rememberPasswordCheckBox.Checked = true;
            }

            fs.Close();
以上就简单的实现了用户登录记住密码的功能。


2018-08-28 18:16:31 qq_21509637 阅读数 1057
  • C#急速入门

    Unity开发,C#绝对是基础中的基础,课程针对纯小白而设计,各种语言细节在课程里均有涉猎,从原理到实战,从底层到算法,你想了解的C#,这里应有尽有,除了讲解,还有练习,你说棒不棒,哈哈,当然如果你是有其他语言基础的同学,课程依然会让你收货满满。来吧,我们进入正题。

    13893 人正在学习 去看看 张建飞

最近做WPF项目有一个需要记住账号密码的操作,第一反应像这种记住账号密码的应该可以保存在本地xml配置文件中,于是就去查了下别人的资料,自己加以整理学习。


WPF应用程序中有一个App.config文件,编译时会在Debug文件夹下生成一个“程序集名称+.exe.config”的xml文件,记录一些配置项。废话不多说,下面开始来完成记住账号密码这个需求:

1.首先在App.config中的<configuration>中添加以下代码,最常用的就是appSettings节点了,通过添加key和value键值对,从而完成参数的配置与读写操作,其中key是键,value是具体保存的值,在这声明了三个,分别是账号、密码和是否记住这三组kv键值对。

  <appSettings>
    <add key="userName" value="admin"/>
    <add key="password" value="1"/>
    <add key="isRemember" value="true"/>
  </appSettings>

2.前台放上账号,密码和是否记住这几个控件,后台需要引用System.Configuration.dll这个类库,这个类库提供了对客户端应用程序配置文件的访问方法。以下是对配置文件中键值对读写操作的方法:

1)读的方法根据传入键名去找对应的值返回。

2)写的方法传入键值,不为NULL则跟新配置文件。

        /// <summary>
        /// 读取客户设置
        /// </summary>
        /// <param name="settingName"></param>
        /// <returns></returns>
        public static string GetSettingString(string settingName)
        {
            try
            {
                string settingString = ConfigurationManager.AppSettings[settingName].ToString();
                return settingString;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 更新设置
        /// </summary>
        /// <param name="settingName"></param>
        /// <param name="valueName"></param>
        public static void UpdateSettingString(string settingName, string valueName)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            if (ConfigurationManager.AppSettings[settingName] != null)
            {
                config.AppSettings.Settings.Remove(settingName);
            }
            config.AppSettings.Settings.Add(settingName, valueName);
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

初始化的时候读取配置赋值:

            txtUsername.Text = GetSettingString("userName");
            txtPassword.Text = GetSettingString("password");
            if (GetSettingString("isRemember") == "true")
            {
                ckbRemember.IsChecked = true;
            }
            else
            {
                ckbRemember.IsChecked = false;
            }

登陆成功,修改配置:

                UpdateSettingString("userName", txtUsername.Text);
                UpdateSettingString("password", txtPassword.Text);
                UpdateSettingString("isRemember", "true");

下面放上所有代码(新手写的不好,仅供参考):

前台Xaml:

<Window x:Class="WpfApplication7.MainWindow"
        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:WpfApplication7"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="550">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="30">账号:</TextBlock>
        <TextBox Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40" FontSize="30" x:Name="txtUsername">
            <TextBox.Resources>
                <VisualBrush x:Key="HintText" TileMode="None" Opacity="0.5" Stretch="None" AlignmentX="Left">
                    <VisualBrush.Visual>
                        <TextBlock FontStyle="Italic" FontSize="30" Text="请输入用户名"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </TextBox.Resources>
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <Trigger Property="Text" Value="{x:Null}">
                            <Setter Property="Background" Value="{StaticResource HintText}"/>
                        </Trigger>
                        <Trigger Property="Text" Value="">
                            <Setter Property="Background" Value="{StaticResource HintText}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <TextBlock Grid.Row="1" Grid.Column="0"  HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="30">密码:</TextBlock>
        <TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40" FontSize="30" x:Name="txtPassword">
            <TextBox.Resources>
                <VisualBrush x:Key="HintText" TileMode="None" Opacity="0.5" Stretch="None" AlignmentX="Left">
                    <VisualBrush.Visual>
                        <TextBlock FontStyle="Italic" FontSize="30" Text="请输入密码"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </TextBox.Resources>
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <Trigger Property="Text" Value="{x:Null}">
                            <Setter Property="Background" Value="{StaticResource HintText}"/>
                        </Trigger>
                        <Trigger Property="Text" Value="">
                            <Setter Property="Background" Value="{StaticResource HintText}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <CheckBox Grid.Row="2" Grid.Column="0"  HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="30" x:Name="ckbRemember"></CheckBox>
        <TextBlock Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="30">记住我</TextBlock>
        <Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30" Click="Button_Click">登录</Button>
    </Grid>
</Window>

后台C#:

using System;
using System.Windows;
using System.Configuration;

namespace WpfApplication7
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            txtUsername.Text = GetSettingString("userName");
            txtPassword.Text = GetSettingString("password");
            if (GetSettingString("isRemember") == "true")
            {
                ckbRemember.IsChecked = true;
            }
            else
            {
                ckbRemember.IsChecked = false;
            }

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (Convert.ToBoolean(ckbRemember.IsChecked))
            {
                UpdateSettingString("userName", txtUsername.Text);
                UpdateSettingString("password", txtPassword.Text);
                UpdateSettingString("isRemember", "true");
                MessageBox.Show("登录并记住密码!");
            }
            else
            {
                UpdateSettingString("userName", "");
                UpdateSettingString("password", "");
                UpdateSettingString("isRemember", "");
                MessageBox.Show("登录不记住密码!");
            }
           
        }

        /// <summary>
        /// 读取客户设置
        /// </summary>
        /// <param name="settingName"></param>
        /// <returns></returns>
        public static string GetSettingString(string settingName)
        {
            try
            {
                string settingString = ConfigurationManager.AppSettings[settingName].ToString();
                return settingString;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 更新设置
        /// </summary>
        /// <param name="settingName"></param>
        /// <param name="valueName"></param>
        public static void UpdateSettingString(string settingName, string valueName)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            if (ConfigurationManager.AppSettings[settingName] != null)
            {
                config.AppSettings.Settings.Remove(settingName);
            }
            config.AppSettings.Settings.Add(settingName, valueName);
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

    }
}

做这个功能的时候发现一些问题,在VS里面编译运行的时候,发现App.config的键值对始终不会变,查了半天资料才知道,App.config文件编译时会在Debug文件夹下生成一个“.exe.config”的xml文件和一个“.vshost.exe.config”的xml文件,编译时修改的是“.vshost.exe.config”文件,直接运行时修改的是“.exe.config”文件,而不是App.config文件。下面是摘抄的网上的资料:

app.config, *.exe.config 和 *.vshost.exe.config区别

1.app.config

      作为开发时配置参数的文件,可以在vs开发时右键属性设置是否复制到可执行程序同目录下(默认始终不复制)。在不复制的情况下,编译生成可执行程序时会copy该文件为*.exe.config文件和*.vshost.exe.config文件。这样的话,在*/bin/debug/ 或者*/bin/release/目录下就不会有app.config文件了,对应的有exe.config和vshost.exe.config。以后运行exe文件所操作的配置文件(通过System.Configuration对象,System.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None))直接修改的是exe.config文件。

2.*.exe.config

     vs调试编译时,如果app.config文件有修改,则会重新copy覆盖到exe.config和vshost.exe.config文件中,否则exe.config不会改变。exe.config文件为程序实际运行时(直接运行.exe程序)直接操作的配置文件。

3.*.vshost.exe.config

    该文件主要是在vs调试运行时起作用,在调试运行程序时(*vshost.exe -> *.exe)先copy *.exe.config覆盖*.vshost.exe.config,然后运行程序时操作的配置文件为*.vshost.exe.config.在调试程序结束时(*.exe -> *.vshost.exe)再次copy *.exe.config覆盖*.vshost.exe.config。 所有调试情况下无论怎么修改配置文件,程序退出后都不会修改配置文件(还原了)。所以在vs调试运行程序时通过配置文件来记录之前的操作无法生效。

      实际release版本的exe程序时,*.vshost.exe.config 和app.config(如果copy了的话)可以不要的,但是*.exe.config文件必须有。


每次做新功能都能学习到一些新东西,当然也会碰到新问题而耽误时间,不管咋样,问题解决就好,快乐工作,快乐学习,一起努力进步吧。o(^▽^)o

2018-11-17 09:26:30 LTyyCFY 阅读数 1308
  • C#急速入门

    Unity开发,C#绝对是基础中的基础,课程针对纯小白而设计,各种语言细节在课程里均有涉猎,从原理到实战,从底层到算法,你想了解的C#,这里应有尽有,除了讲解,还有练习,你说棒不棒,哈哈,当然如果你是有其他语言基础的同学,课程依然会让你收货满满。来吧,我们进入正题。

    13893 人正在学习 去看看 张建飞

在这里插入图片描述
刚开始学编程。学了三个月了,学的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:PasswordBoxHelper.Attach="True" local:PasswordBoxHelper.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 PasswordBoxHelper
    {
        //通过调用PasswordHelper.Attach财产。附加财产PasswordHelper.Password提供PasswordBox控件的原始密码属性的可绑定副本。
        public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.RegisterAttached("Password",
        typeof(string), typeof(PasswordBoxHelper),
        new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));

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

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


        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:PasswordBoxHelper.Attach="True" local:PasswordBoxHelper.Password="{Binding Path=SaveLoginPSW, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></PasswordBox>

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

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

(9)我把保存选项放在登陆按钮上了
这里我是当按下确定时
1.1 账号密码错误,未勾选记住密码 清空账号密码
1.2 账号密码错误,勾选记住密码 账号密码保存
1.3 账号密码正确,未勾选记住密码 清空账号密码,登录进入主窗口
1.4 账号密码正确,勾选记住密码 账号密码保存,登录进入主窗口
关于如何确定账号密码正确与如何进入主界面,参考引用如下

WPF 登陆界面判断输入的用户名和密码是否与数据库中保存的数据相同

https://blog.csdn.net/u010637394/article/details/43833139?utm_source=blogxgwz5

WPF:验证登录后关闭登录窗口,显示主窗口的解决方法

https://blog.csdn.net/Jacee0048/article/details/49952643?utm_source=blogxgwz3

这里主要看using()的那一段代码段,将using代码段写进一个void方法里

        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("请填写用户名和密码");
                SaveOptionsXml();
            }

            else
            {
                if (dr.Read())//判断是否存在用户输入的用户名和密码
                {
                    MessageBox.Show("登陆成功"); // 显示主窗口;
                    this.DialogResult = Convert.ToBoolean(1);
                    SaveOptionsXml();
                    conn.Close();                                                          //关闭数据库连接
                    this.Close();
                }

                else
                {
                    MessageBox.Show("用户名或密码有误");
                    SaveOptionsXml();
                    conn.Close();                                                          //关闭数据库连接
                }
            }
            private void SaveOptionsXml()
        {
            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);
            }
        }
        }

(10)查了半天实现了PasswordBox的水印功能(用的模板和样式)。参考如下

https://www.cnblogs.com/OhMonkey/p/6057076.html

然后查TextBox的水印功能,感觉很麻烦,试过把账号登录框TextBox换成PasswordBox,这样用一个模板样式就可以了。但是发现TextBox换成PasswordBox会问题,账号框输入的文本会显示为小圆点。后面找了半天还是换成TextBox了。
上面网页样式的TextBox样式前面缺了一个缺一段键名TxbBase的样式,补上去就可以直接用了

https://blog.csdn.net/c0411034/article/details/82467916

Style x:Key="TxbBase" TargetType="TextBox">
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="FontSize" Value="20"/>
            <!--光标的颜色-->
            <Setter Property="CaretBrush" Value="Green"/>
            <!--屏蔽系统右键菜单-->
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu Visibility="Collapsed"/>
                </Setter.Value>
            </Setter>
            <!--用来禁用掉中文输入法-->
            <!--<Setter Property="input:InputMethod.IsInputMethodEnabled" Value="False"/>-->
        </Style>

(11)新建一个PasswordBoxHelper类,代码如下(接口可以删掉或保留,我用的vs2017)

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 PasswordBoxHelper
    {
        //通过调用PasswordHelper.Attach财产。附加财产PasswordHelper.Password提供PasswordBox控件的原始密码属性的可绑定副本。
        public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.RegisterAttached("Password",
        typeof(string), typeof(PasswordBoxHelper),
        new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));

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

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


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

(12)PasswordBox的样式如下:
与参考的区别主要是

  1. 命名空间name我的是local,参考是Core
  2. 样式触发器有所不同
 <Trigger Property="local:PasswordBoxWaterMark.PasswordLength" Value="0">
                            <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/>

用参考里面的这里会出现一个问题,就是我选择了记住账号密码,然后登陆退出,重新打开程序,会发现记住的账号密码和水印都存在。
应换成如下代码,(看(9)中的using代码块)因为我没有选择记住账号密码的话,账号密码文本框内容会清空。账号密码框文本为空的时候出现水印才合理。

<Trigger Property="local:PasswordBoxHelper.Password" Value="">
                                <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/>
                            </Trigger>

完成代码如下

<Style TargetType="PasswordBox">
            <!--输入文本框的字体的颜色,水印的颜色在grid空间里面的Textblock文本框中设置-->
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="FontSize" Value="20"/>
            <!--光标的颜色-->
            <Setter Property="CaretBrush" Value="Green"/>
            <Setter Property="local:PasswordBoxWaterMark.IsMonitoring" Value="true"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type PasswordBox}">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <Grid>
                                <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                                <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" Foreground="Red"
                                           VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="local:PasswordBoxHelper.Password" Value="">
                                <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

(13)TextBox样式如下:
文本框的颜色我设的黑色,水印设置为红色

        <Style x:Key="TxbBase" TargetType="TextBox">
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="FontSize" Value="20"/>
            <!--光标的颜色-->
            <Setter Property="CaretBrush" Value="Green"/>
            <!--屏蔽系统右键菜单-->
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu Visibility="Collapsed"/>
                </Setter.Value>
            </Setter>
            <!--用来禁用掉中文输入法-->
            <!--<Setter Property="input:InputMethod.IsInputMethodEnabled" Value="False"/>-->
        </Style>
        <!--触发器的形式进行水印效果-->
        <Style x:Key="TxbTrigger" TargetType="TextBox" BasedOn="{StaticResource TxbBase}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <Grid>
                                <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                                <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5" Foreground="Red"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                            </Trigger>
                            <Trigger Property="IsKeyboardFocused" Value="True">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                            </Trigger>
                            <Trigger Property="Text" Value="">
                                <Setter Property="Visibility" TargetName="WaterMark" Value="Visible"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

(14)TextBox和PasswordBox空间完整代码如下:

<TextBox Name="txt_UserName" Margin="20,0,5,10" Tag="请输入账号" Style="{StaticResource TxbTrigger}" Text="{Binding Path=SaveLoginID}"
                                 HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40" SnapsToDevicePixels="True" VerticalContentAlignment="Center"></TextBox>
<PasswordBox Name="txt_PSW" Margin="20,0,5,0" PasswordChar="●" Tag="请输出密码"
                                 local:PasswordBoxHelper.Attach="True" local:PasswordBoxHelper.Password="{Binding Path=SaveLoginPSW,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                 HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40" SnapsToDevicePixels="True" VerticalContentAlignment="Center"></PasswordBox>

效果如图

在这里插入图片描述
在这里插入图片描述

2018-08-06 11:35:58 qq_36577699 阅读数 6014
  • C#急速入门

    Unity开发,C#绝对是基础中的基础,课程针对纯小白而设计,各种语言细节在课程里均有涉猎,从原理到实战,从底层到算法,你想了解的C#,这里应有尽有,除了讲解,还有练习,你说棒不棒,哈哈,当然如果你是有其他语言基础的同学,课程依然会让你收货满满。来吧,我们进入正题。

    13893 人正在学习 去看看 张建飞

登录界面如下  

配置文件如下  在App.config下 写个<appSettings>节点  照着我的写就行了

单击登录时 

  Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (IsLogin.Checked)
            {
                cfa.AppSettings.Settings["autologin"].Value = "true";
                cfa.AppSettings.Settings["rememberme"].Value = "true";
                cfa.AppSettings.Settings["name"].Value = name.Text;
                cfa.AppSettings.Settings["password"].Value = password.Text;
                cfa.Save();
            }
            else {
                if (IsPassword.Checked)
                {
                    cfa.AppSettings.Settings["autologin"].Value = "false";
                    cfa.AppSettings.Settings["rememberme"].Value = "true";
                    cfa.AppSettings.Settings["name"].Value = name.Text;
                    cfa.AppSettings.Settings["password"].Value = password.Text;
                    cfa.Save();
                }
                else
                {
                    cfa.AppSettings.Settings["autologin"].Value = "false";
                    cfa.AppSettings.Settings["rememberme"].Value = "false";
                    cfa.AppSettings.Settings["name"].Value = "";
                    cfa.AppSettings.Settings["password"].Value = "";
                }
            }
            cfa.Save();

最后写到 文件 WindowsFormsApp1\WindowsFormsApp1\bin\Debug  下的 WindowsFormsApp1.exe.Config  我的是这个目录 你们自己找下自己的目录下的这个文件 看有没有信息

然后就是窗体加载事件里边写

            //如果记住密码为true 那么把值 赋值给文本框
            if (ConfigurationManager.AppSettings["rememberme"].Equals("true"))
            {
                name.Text = ConfigurationManager.AppSettings["name"];
                password.Text = ConfigurationManager.AppSettings["password"];
                IsPassword.Checked = true;
            }
            //如果是自动登录  那么拿获取 配置文件中的账号密码  然后到数据库里边查询 登录
            if (ConfigurationManager.AppSettings["autologin"].Equals("true")) {
                IsLogin.Checked = true;
            }

注意: 需要添加引用:引入System.Configuration

没有更多推荐了,返回首页