美文网首页WPF
使用 WPF 和 MySQL 搭建小型人资管理系统——登录页与主

使用 WPF 和 MySQL 搭建小型人资管理系统——登录页与主

作者: Alpenbelieve | 来源:发表于2019-01-27 17:45 被阅读244次

    终于开始写第二篇了... 加油加油,我要坚持写完这个系列...
    从这一篇开始,我会从项目的流程和结构角度来介绍,中间穿插介绍遇到的问题和坑。

    开始!


    (本篇主要介绍登录页和主界面的框架布局)

    项目情况说明

    主要功能:对员工信息进行增删改查,生成特定格式的评估表单并打印,用户管理(可能有多个使用者通过不同的用户名和密码登录,需要管理)
    用户:高管以及人资部门的员工。前者通过程序查看员工的详细信息不进行其他操作,后者通过程序来编辑和管理员工的信息。
    部署方式:我们把程序部署在公司人资部的几台电脑上,把员工信息数据库部署在公司服务器上。(不宜把这样的数据库放在个人电脑上,一是不安全,二是不能满足绝大多数时间都能提供服务的要求)

    程序和界面逻辑

    首先需要登录,登录成功后,可进入“人事管理”、“用户管理”、“数据备份”、“帮助页面”。重点说一下人事管理页面,在此页面中可看到员工的信息表,并可查看每个员工的详细信息,以及进行添加、修改和删除操作。

    登录界面

    WPF 的界面通过拖拽就可以生成,我的做法是先拖拽出一个大致的界面,再通过 visual studio 侧边的属性栏或者修改 XAML 代码来进行更精细的调节,比如控制字号、颜色或对齐方式等。经过一顿折腾,做出来了如下的界面:(图标来自 Iconfont,阿里的矢量图标库)

    登录界面.png
    开发过程中,遇到了许多大大小小的问题,依据回忆依次记录如下...
    • 如何引用这些图标?

    百度这个问题,可以有好几种解决方式,这里给出两种比较简单的,一是使用绝对路径,也就是在 image 标签中加上 Source="C:\Users\admin\Desktop\icon\password.png"这样的路径说明就可以。但是这样的话相当于写死了代码,不是很推荐。我最终使用的是第二种方式,即相对路径。先在项目目录下新建一个文件夹并右键添加现有项,然后用如图所示的方式来进行引用即可。

    相对路径的使用.png
    • 用户名使用的是 WPF 自带的 TextBox 控件,如何显示灰字提示?

    在 XAML 的TextBox中加上如下代码:

                    <TextBox.Resources>
                        <VisualBrush x:Key="HelpBrush"
                                     Opacity="0.4"
                                     Stretch="None"
                                     AlignmentX="Left">
                            <VisualBrush.Visual>
                                <TextBlock  Text="请输入用户名"
                                            FontSize="16" />
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </TextBox.Resources>
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Style.Triggers>
                                <Trigger Property="Text"
                                         Value="">
                                    <Setter Property="Background"
                                            Value="{StaticResource HelpBrush}" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
    
    • 密码框使用的是 WPF 自带的 PasswordBox 控件,但是由于提供给我们的属性有限,它并不能像 TextBox 那样设置提示信息,怎么办?

    答案是只能自己实现一个...好在 Stackoverflow 上已经有人解决了这个问题,首先我们需要在 XAML 对应的 .cs 文件中的类后面加上下面的类和方法:

    public class PasswordBoxMonitor : DependencyObject
        {
            public static bool GetIsMonitoring(DependencyObject obj)
            {
                return (bool)obj.GetValue(IsMonitoringProperty);
            }
    
            public static void SetIsMonitoring(DependencyObject obj, bool value)
            {
                obj.SetValue(IsMonitoringProperty, value);
            }
    
            public static readonly DependencyProperty IsMonitoringProperty =
                DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxMonitor), new UIPropertyMetadata(false, OnIsMonitoringChanged));
    
            public static int GetPasswordLength(DependencyObject obj)
            {
                return (int)obj.GetValue(PasswordLengthProperty);
            }
    
            public static void SetPasswordLength(DependencyObject obj, int value)
            {
                obj.SetValue(PasswordLengthProperty, value);
            }
    
            public static readonly DependencyProperty PasswordLengthProperty =
                DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxMonitor), new UIPropertyMetadata(0));
    
            private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var pb = d as PasswordBox;
                if (pb == null)
                {
                    return;
                }
                if ((bool)e.NewValue)
                {
                    pb.PasswordChanged += PasswordChanged;
                }
                else
                {
                    pb.PasswordChanged -= PasswordChanged;
                }
            }
    
            static void PasswordChanged(object sender, RoutedEventArgs e)
            {
                var pb = sender as PasswordBox;
                if (pb == null)
                {
                    return;
                }
                SetPasswordLength(pb, pb.Password.Length);
            }
        }
    

    接下来返回到 XAML 文件中,在开头的地方(我们定义的第一个控件之前)加上下面一段定义 PasswordBox 属性的代码:

    <Window.Resources>
            <Style x:Key="{x:Type PasswordBox}"
                   TargetType="{x:Type PasswordBox}">
                <Setter Property="DatabaseProject:PasswordBoxMonitor.IsMonitoring"
                        Value="True" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type PasswordBox}">
                            <Border Name="Bd"
                                    Background="{TemplateBinding Background}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    SnapsToDevicePixels="true">
                                <Grid>
                                    <ScrollViewer x:Name="PART_ContentHost"
                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                    <TextBlock Text="请输入密码"
                                               Margin="4, 6, 0, 0"
                                               Foreground="#999999"
                                               FontSize="16"
                                               Visibility="Collapsed"
                                               Name="txtPrompt" />
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsEnabled"
                                         Value="false">
                                    <Setter TargetName="Bd"
                                            Property="Background"
                                            Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                                    <Setter Property="Foreground"
                                            Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                                </Trigger>
                                <Trigger Property="DatabaseProject:PasswordBoxMonitor.PasswordLength"
                                         Value="0">
                                    <Setter Property="Visibility"
                                            TargetName="txtPrompt"
                                            Value="Visible" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
    

    虽然看着多,但是思路还是很清楚的,相当于先写个类,再定义属性,就可以在属性中设置灰色的提示文字了。

    除了这些问题,登录时还需要与数据库内容进行比较,从而验证用户名和密码是否正确匹配。这部分内容现在先不写,准备放到后面和其他数据库操作一起讲 : )

    主界面

    主界面大致长这样:(不要嫌弃它太空,这是个演示...)


    主界面.png

    可以将它作为一个欢迎页面,在里面加上提示性文字或注意事项。

    • 如何写这样的界面?如何实现点击不同的菜单栏就跳转到不同的页面?

    页面布局使用了 DockPanel,这是一种可以使元素停靠在页面特定方向的布局。此处先定义了顶部和底部的元素(即菜单和状态栏),然后再定义 Frame,这样 Frame 就会位于中间。Frame 的作用是嵌入某个 Page 到 Window 中,此处将显示欢迎信息和注意事项的 WelcomePage 放在了主界面中,并禁用了导航栏。当点击菜单项时,Frame 可以显示其他 Page 的内容。简化后的页面元素如下所示:

    <Viewbox>
            <!--通过Viewbox可以实现缩放页面时其中的元素也跟着缩放的效果,用于屏幕适配-->
            <Canvas Height="1000"
                    Width="1920">
                <DockPanel Background="#F9F9F9"
                           LastChildFill="False"
                           Height="1000"
                           Width="1920">
                    <Menu DockPanel.Dock="Top">
                        <!--给四个菜单项添加监听事件-->
                        <MenuItem Header="人事管理"
                                  Click="RenShi_Click"/>
                        <MenuItem Header="用户管理"
                                  Click="YongHu_Click"/>
                        <MenuItem Header="数据备份"
                                  Click="BeiFen_Click"/>
                        <MenuItem Header="帮助"
                                  Click="BangZhu_Click"/>
                    </Menu>
                    <StatusBar DockPanel.Dock="Bottom"/>
                    <Frame x:Name="mainframe"
                           Source="WelcomePage.xaml"
                           NavigationUIVisibility="Hidden"></Frame>
                </DockPanel>
            </Canvas>
        </Viewbox>
    

    在 .cs 文件中,以人事管理菜单项的点击事件为例,通过public static Page1 p1;定义静态变量 p1,其中 Page1 是另一个新建的 Page 如下所示:

    private void RenShi_Click(object sender, RoutedEventArgs e)
            {
                if (p1 == null)
                {
                    p1 = new Page1(page1_para);
                }
                //通过Navigate方法可以让Frame显示p1的内容,从而实现跳转
                mainframe.Navigate(p1);
            }
    

    这样就可以点击实现菜单栏跳转的功能了。

    OK,这篇就写到这里,下一篇会阐述不同页面之间的关系,以及每个页面中比较难实现的部分,下次见~~~

    相关文章

      网友评论

        本文标题:使用 WPF 和 MySQL 搭建小型人资管理系统——登录页与主

        本文链接:https://www.haomeiwen.com/subject/xjigjqtx.html