WPF範例系列一:登入、註冊介面設計

2021-04-22 10:00:09

WPF範例系列一:登入、註冊介面設計



前言

本範例將展示利用WPF設計登入介面、註冊介面,並實現相應的功能,其中賬戶資料將儲存在excel表中。


一、範例演示

1. 登入介面展示

​​​在這裡插入圖片描述

2. 註冊介面展示

在這裡插入圖片描述

3. 資料儲存

在這裡插入圖片描述

4. 效果演示

在這裡插入圖片描述

二、結構及原始碼

1.主介面跳轉登入介面設計

MainWindow.xaml.cs跳轉登入介面程式碼如下:

using System;
using System.Windows;
using System.Windows.Threading;

namespace sample5
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        //public int play_state = 1;  
        public MainWindow()
        {
            InitializeComponent();

            #region 登入介面載入及驗證
            //顯示登陸介面,驗證後返回。
            LoginWindow loginWindow = new LoginWindow();
            loginWindow.ShowDialog();
            if (loginWindow.DialogResult != Convert.ToBoolean(1))
            {
                this.Close();
            }
            //顯示登陸介面 結束
            #endregion 
         }
     }
 }     

2.登入介面設計

Xaml程式碼如下(新增1個Nuget庫:MaterialDesignThemes.3.1.0-ci981 ;可參考):

<Window x:Class="sample5.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        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:sample5"
        mc:Ignorable="d"
        Title="使用者登入" Height="500" Width="350" 
        ResizeMode="NoResize" 
        WindowStartupLocation="CenterScreen" 
        WindowStyle="None" 
        MouseLeftButtonDown="MoveWindow_MouseLeftButtonDown"
        FontFamily="Segoe UI Emoji">

    <Grid>
        <Rectangle Height="280" VerticalAlignment="Top">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF2281D1"/>
                    <GradientStop Color="#FF34268A" Offset="1"/>
                    <GradientStop Color="#FF33288B" Offset="0.546"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Height=" 220" VerticalAlignment="Bottom" >
            <Rectangle.Fill>
                <SolidColorBrush Color="Snow" />
            </Rectangle.Fill>
        </Rectangle>

        <Rectangle Width="280" Height="240" VerticalAlignment="Bottom" Margin="0,80" RadiusY="10" RadiusX="10" Fill="White">
            <Rectangle.Effect>
                <DropShadowEffect BlurRadius="15" Direction="0" RenderingBias="Quality" ShadowDepth="1" Color="#FFBBBBBB"/>
            </Rectangle.Effect>
        </Rectangle>
        
        <Grid VerticalAlignment="Bottom" Margin="35,80" Height="240">
            <Label Content="登入" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5" Foreground="Gray" FontSize="18"/>
            <StackPanel VerticalAlignment="Center" Margin="15">
                <TextBox x:Name="Account" Margin="0,5" materialDesign:HintAssist.Hint="賬號" Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="16"/>
                <PasswordBox x:Name="Password" Margin="0,5" materialDesign:HintAssist.Hint="密碼" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" FontFamily="Champagne &amp; Limousines" FontSize="16"/>
            </StackPanel>
        </Grid>

        <Button Width="150" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,65" Content="LOGIN" Click="Login_Button"/>

        <TextBlock Text="註冊賬戶" HorizontalAlignment="Left"  VerticalAlignment="Bottom" Margin="60 40" FontSize="13" Foreground="Gray"  Cursor="Hand" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"/>

        <TextBlock Text="忘記密碼?" HorizontalAlignment="Right " VerticalAlignment="Bottom" Margin="60 40"  FontSize="13" Foreground="Gray"  Cursor="Hand"/>


        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" Click="Close_Click" >
            <materialDesign:PackIcon Kind="Close"/>
        </Button>

        <Border CornerRadius="30" BorderBrush="#FF2281D1" BorderThickness="2" Width="100" Height="100" VerticalAlignment="Top" Margin="30">
            <Border.Background>
                <ImageBrush ImageSource="./picture/Loginbackground.jpg"/>
            </Border.Background>
        </Border>
         
    </Grid>
</Window>

後臺程式碼如下(LoginWindow.xaml.cs):

using System;
using System.Collections;
using System.Windows;
using System.Windows.Input;
using Window = System.Windows.Window;

namespace sample5
{
    /// <summary>
    /// LoginWindow.xaml 的互動邏輯
    /// </summary>
    public partial class LoginWindow : Window
    {
        public string UserName;
        public string UserPassword;
        public int border = 1;
        public static Hashtable userall_harsh;

        public LoginWindow()
        {
            InitializeComponent();
        }

        private void MoveWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }

        private void Close_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }


        private void Login_Button(object sender, RoutedEventArgs e)
        {
            ExcelSave excel1 = new ExcelSave();
            userall_harsh = excel1.readExcel();

            if (userall_harsh == null)
            {
                MessageBox.Show("無此賬戶,請先註冊!");
                return;
            }
            else
            {               
                
                IDictionaryEnumerator myEnumerator = userall_harsh.GetEnumerator();  //讀取harshtable中的key和value值
                while (myEnumerator.MoveNext()) //將列舉數推到集合的下一元素,若為空,則退出迴圈
                {

                    UserName = myEnumerator.Key.ToString();         //key值賦給UserName
                    UserPassword = myEnumerator.Value.ToString();    //value值賦給UserPassword

                    if (Account.Text.ToString() == UserName && Password.Password.ToString() == UserPassword)
                    {
                        this.DialogResult = Convert.ToBoolean(1);
                        this.Close();
                        break;
                    }
                    else if (border<=userall_harsh .Count-1)      //給迴圈一邊界,若迴圈到所存資料最後一個數仍然不正確,則執行else語句
                    {
                        border++;
                    }                        
                    else
                        MessageBox.Show("賬號或密碼錯誤,請重試!");
                }
            }
        }


        //「註冊賬戶」TextBlock觸發事件
        private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            RegisterWindow register1 = new RegisterWindow();  //Login為視窗名,把要跳轉的新視窗範例化
            this.Close();  //關閉當前視窗
            register1.ShowDialog();   //開啟新視窗          
        }
    }
}

3.註冊介面設計

Xaml程式碼如下:

<Window x:Class="sample5.RegisterWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        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:sample5"
        mc:Ignorable="d"
        Title="使用者登入" Height="500" Width="350" 
        ResizeMode="NoResize" 
        WindowStartupLocation="CenterScreen" 
        WindowStyle="None" 
        MouseLeftButtonDown="MoveWindow_MouseLeftButtonDown"
        FontFamily="Segoe UI Emoji">
    <Grid>
        <Rectangle Height="280" VerticalAlignment="Top">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF2281D1"/>
                    <GradientStop Color="#FF34268A" Offset="1"/>
                    <GradientStop Color="#FF33288B" Offset="0.546"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Height=" 220" VerticalAlignment="Bottom" >
            <Rectangle.Fill>
                <SolidColorBrush Color="Snow" />
            </Rectangle.Fill>
        </Rectangle>

        <Rectangle Width="280" Height="240" VerticalAlignment="Bottom"  Margin="0,80" RadiusY="10" RadiusX="10" Fill="White" >
            <Rectangle.Effect>
                <DropShadowEffect BlurRadius="15" Direction="0" RenderingBias="Quality" ShadowDepth="1" Color="#FFBBBBBB"/>
            </Rectangle.Effect>
        </Rectangle>

        <Grid VerticalAlignment="Bottom" Margin="35,80" Height="240">
            <Label Content="使用者註冊" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5" Foreground="Black" FontSize="18"/>
            <StackPanel VerticalAlignment="Center" Margin="20">
                <TextBox x:Name="Re_Account" Margin="0,5" materialDesign:HintAssist.Hint="請輸入賬號" Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="16"/>
                <PasswordBox x:Name="Re_Password" Margin="0,5" materialDesign:HintAssist.Hint="請輸入密碼" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" FontFamily="Champagne &amp; Limousines" FontSize="16"/>
                <PasswordBox x:Name="Re_PasswordAgain" Margin="0,5" materialDesign:HintAssist.Hint="請確認密碼" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" FontFamily="Champagne &amp; Limousines" FontSize="16"/>
            </StackPanel>
        </Grid>

        <Button Width="150" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,65" Content="Register" Click="Register_Button"/>

        <Border CornerRadius="30" BorderBrush="#FF2281D1" BorderThickness="2" Width="100" Height="100" VerticalAlignment="Top" Margin="30">
            <Border.Background>
                <ImageBrush ImageSource="./picture/Registerbackground.jpg"/>
            </Border.Background>
        </Border>

        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" Click="ReClose_Click" >
            <materialDesign:PackIcon Kind="Close"/>
        </Button>

    </Grid>
</Window>

後臺程式碼如下:

using System;
using System.Collections;
using System.Windows;
using System.Windows.Input;
using Window = System.Windows.Window;


namespace sample5
{
    /// <summary>
    /// RegisterWindow.xaml 的互動邏輯
    /// </summary>
    public partial class RegisterWindow : Window
    {

        public static Hashtable userall;
        public RegisterWindow()
        {
            InitializeComponent();
        }
        private void MoveWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }

        private void ReClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void Register_Button(object sender, RoutedEventArgs e)
        {
            string u = Re_Account.Text.ToString();
            string p = Re_Password.Password.ToString();
            string rp = Re_PasswordAgain.Password.ToString();
            ExcelSave excel = new ExcelSave();


            if (String.IsNullOrEmpty(u))
            {
                MessageBox.Show("user is not null");
                return;
            }
            if (String.IsNullOrEmpty(p))
            {
                MessageBox.Show("password is not null");
                return;
            }
            if (String.IsNullOrEmpty(rp))
            {
                MessageBox.Show("Repassword is not null");
                return;
            }
            if (!p.Equals(rp))
            {
                MessageBox.Show("password is not equals repassword");
                return;
            }

            userall = excel.readExcel();  //讀取excel資料
            if (userall == null)
            {
                userall = new Hashtable();
                userall.Add(u, p);
            }
            else
            {
                bool isexist = userall.ContainsKey(u);  //判斷使用者是否存在
                if (isexist)
                {
                    MessageBox.Show("user is exist!");
                    return;
                }
                else
                {
                    userall.Add(u, p);
                    Console.WriteLine(userall.Count);
                }
            }

            System.Windows.Application.Current.Properties["users"] = userall;   //類似於Session的功能,使用者登入後,可以將使用者的資訊儲存在Properties中。
            excel.InsertExcel(u, p);
            MessageBox.Show("regist success!");


            MainWindow main = new MainWindow();
            main.WindowStartupLocation = WindowStartupLocation.Manual;   //使新視窗位置在原來的位置上
            main.Left = this.Left;  //使新視窗位置在原來的位置上
            main.Top = this.Top;  //使新視窗位置在原來的位置上
            this.Close();
            main.ShowDialog();  //開啟新視窗         
        }
    }
}

4.Excel儲存資料類設計

學習使用Csharp處理excel表,建立ExcelSave.cs:

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Collections;
using System.Windows;

namespace sample5
{

    public class ExcelSave
    {
        Excel.Application ExcelApp = new Excel.Application();
        #region 建立excel工作簿
        public void InsertExcel(string u, string p)
        {
            //1.建立Excel

            try
            {
                //2.開啟已經存在的工作簿
                string path = "C:\\Users\\非黑不即白\\Desktop\\code.xlsx";
                ExcelApp.Workbooks.Open(path, ReadOnly: false);

                //3.
                ExcelApp.Cells[1, 1].Value = "username";
                ExcelApp.Cells[1, 2].Value = "password";

                int RowCount = ExcelApp.ActiveSheet.UsedRange.Rows.Count + 1;
                //ExcelApp.ActiveSheet.Rows[RowCount].Insert(u, p);

                ExcelApp.Cells[RowCount, 1].Value = u;
                ExcelApp.Cells[RowCount, 2].Value = p;


                ExcelApp.DisplayAlerts = false; //儲存Excel的時候,不彈出是否儲存的視窗直接進行儲存 
                //4.儲存工作表
                ExcelApp.ActiveWorkbook.Save();

            }
            catch
            {
                MessageBox.Show("匯出檔案儲存失敗,可能原因該檔案已開啟!", "警告!");
            }
            finally
            {
                //5.關閉工作簿
                ExcelApp.ActiveWorkbook.Close();
                //6.退出excel
                ExcelApp.Quit();
                // PublicMethod.Kill(ExcelApp);
            }

        }
        #endregion

        #region 讀取excel工作簿資料
        public Hashtable readExcel()
        {
            try
            {
                //2.開啟已經存在的工作簿
                string path = "C:\\Users\\非黑不即白\\Desktop\\code.xlsx";
                //ExcelApp.Workbooks.Open(path, ReadOnly: true);
                Hashtable h = new Hashtable();


                Excel.Workbook wb = ExcelApp.Application.Workbooks.Open(path, ReadOnly: true); //取得工作簿
                Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets.get_Item(1);

                int rowsint = ws.UsedRange.Cells.Rows.Count; //得到行數

                Excel.Range rng1 = ws.Cells.get_Range("A2", "A" + rowsint); // 取得資料範圍區域(不包括標題列)
                Excel.Range rng2 = ws.Cells.get_Range("B2", "B" + rowsint);

                string[,] arry = new string[rowsint - 1, 2];  //將新值賦給一個陣列

                if (rowsint <= 1)
                {
                    //MessageBox.Show("無賬戶資訊,請先註冊!");  LoginWindow已做判斷,無需重複
                    return null;
                }
                else
                {
                    if (rowsint == 2)  //解決表格有一個資料使用者,再新增時報錯的問題
                    {
                        arry[0, 0] = rng1.Value2.ToString();   //rng.value2獲取單元格資料
                        arry[0, 1] = rng2.Value2.ToString();
                        h.Add(rng1.Value2.ToString(), rng2.Value2.ToString());
                        Console.WriteLine(rng1.Value2.ToString() + " :" + rng2.Value2.ToString());
                        return h;
                    }
                    else
                    {
                        for (int i = 1; i <= rowsint - 1; i++)
                        {
                            arry[i - 1, 0] = rng1.Value2[i, 1].ToString();   //rng.value2獲取單元格資料
                            arry[i - 1, 1] = rng2.Value2[i, 1].ToString();
                            h.Add(rng1.Value2[i, 1].ToString(), rng2.Value2[i, 1].ToString());
                            Console.WriteLine(rng1.Value2[i, 1].ToString() + " :" + rng2.Value2[i, 1].ToString());
                        }
                        return h;
                    }
                }
            }
            catch
            {
                MessageBox.Show("read excel error");
                return null;
            }
            finally
            {
                //5.關閉工作簿
                ExcelApp.ActiveWorkbook.Close();
                //6.退出excel
                ExcelApp.Quit();
                //PublicMethod.Kill(ExcelApp); //關閉excel後臺程序,此處無需新增
            }
        }
        #endregion
    }

    /* 關閉excel後臺程序
    public class PublicMethod
    {
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        public static void Kill(Excel.Application excel)
        {
            IntPtr t = new IntPtr(excel.Hwnd);//得到這個控制程式碼,具體作用是得到這塊記憶體入口 

            int k = 0;
            GetWindowThreadProcessId(t, out k);   //得到本程序唯一標誌k
            System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);   //得到對程序k的參照
            p.Kill();     //關閉程序k
        }
    }*/
}

5.原始碼

結構總覽:
在這裡插入圖片描述

原始碼:點選跳轉地址


參考文獻
1. 少量程式碼設計一個登入介面 - .NET CORE(C#) WPF開發
2.頁面跳轉
3.WPF註冊登入頁面,同時將註冊資訊儲存到一個excel中
4.C#匯出資料到Excel的幾種方法
補充學習