星期四, 7月 30, 2015

[C#] 使用者控制項 Part2

在 MSDN 發現這篇 2002 年文章 Creating a Windows Form User Control,動手實作並把文章內的 Code 整理起來

[C#] 使用者控制項 Part2-1


  • T-SQL 相關
USE [AdventureWorks2014]
GO

IF OBJECT_ID('Employees') IS NOT NULL
    DROP TABLE Employees

CREATE TABLE Employees
(
    EmpID int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
    EmpNO char(6) NULL ,
    LastName varchar(25) NULL ,
    FirstName char(15) NULL ,
    Salary money NULL
)
GO

INSERT INTO Employees (EmpNO,LastName,FirstName,Salary) VALUES
    ('MS-001','Tsai','Terry',22000) ,
    ('MS-002','Cheng','Vivan',50000)
GO

CREATE PROCEDURE uspCheckEmpNOValid(@EmpNO char(6))
AS
  BEGIN
  
    IF EXISTS
    (
      SELECT 1 FROM Employees WHERE EmpNO = @EmpNO
    )
        RETURN 1
    ELSE
        RETURN 0
    END
GO
[C#] 使用者控制項 Part2-2
  • UserControl EmployeeNumber 相關
using System.Data.SqlClient;

namespace PKUserControl
{
    public partial class EmployeeNumber : UserControl
    {

        // Connecton String
        [Description("連線字串"),Category("自定屬性")]
        public string ConnectionString { get; set; }

        // 利用 UserControl Text 屬性來接收 TextBox 值
        public override string Text
        {
            get
                {
                    return txtEmpNO.Text;
                }
            set
                {
                    txtEmpNO.Text = value;
                }
        }

        #region EmpNO Event 相關
        public enum EmpNOErrors
        {
            NoError = 0,
            NotLongEnough = 1,
            LetterMissing = 2,
            DashMissing = 3,
            NumberMissing = 4
        }

        public class EmpNOCheckEventArgs : EventArgs
        {
            [Description("錯誤訊息")]
            public string Message { get; set; }
            [Description("錯誤碼")]
            public EmpNOErrors Error { get; set; }
        }

        public delegate void EmpNOCheckEventHandler(object sender, EmpNOCheckEventArgs e);

        public event EmpNOCheckEventHandler EmpNOCheck;

        protected virtual void OnEmpNOCheck(EmpNOCheckEventArgs e)
        {
            if (EmpNOCheck != null)
                EmpNOCheck(this, e);
        }
        #endregion

        public bool EmpNOCheckDAO()
        {

            bool result = false;

            try
            {
                using (SqlConnection conn = new SqlConnection(this.ConnectionString))
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "uspCheckEmpNOValid";
                    cmd.Parameters.AddWithValue("@EmpNO", this.Text);

                    // 定義 Parameter 來接收 Store Procedure 的 return 值
                    SqlParameter retValue = new SqlParameter();
                    retValue.Direction = ParameterDirection.ReturnValue;
                    cmd.Parameters.Add(retValue);

                    if (conn.State != ConnectionState.Open)
                        conn.Open();

                    cmd.ExecuteNonQuery();

                    // 把 object 轉為 bool 回傳
                    result = Convert.ToBoolean(retValue.Value);
                }
            }
            catch (Exception)
            {
                throw;
            }

            return result;
        }

        private void txtEmpNO_Validating(object sender, CancelEventArgs e)
        {
            string Message = string.Empty;
            EmpNOErrors Error = EmpNOErrors.NoError;

            string EmpNO = txtEmpNO.Text.Trim();

            // 判斷是否為空值
            if (string.IsNullOrEmpty(EmpNO))
            {
                Error = EmpNOErrors.NumberMissing;
                Message = "沒有輸入任何資料";
            }

            // 判斷輸入資料是否小於六個字元
            if (Error == EmpNOErrors.NoError && EmpNO.Length < 6)
            {
                Error = EmpNOErrors.NotLongEnough;
                Message = "資料不足六碼";
            }

            // 確定前兩碼是字元
            if (Error == EmpNOErrors.NoError)
            {
                for (int i = 0; i < 1; i++)
                {
                    if (!char.IsLetter(EmpNO, i))
                    {
                        Error = EmpNOErrors.LetterMissing;
                        Message = "前兩碼必須是字元";
                        break;
                    }
                }
            }

            // 第三碼必須是 dash (-) 符號
            if (Error == EmpNOErrors.NoError && EmpNO.Substring(2, 1) != "-")
            {
                Error = EmpNOErrors.DashMissing;
                Message = "第三碼必須是 - 符號";
            }

            // 最後三碼必須是數字
            if (Error == EmpNOErrors.NoError)
            {
                for (int i = 3; i < 5; i++)
                {
                    if (!char.IsDigit(EmpNO, i))
                    {
                        Error = EmpNOErrors.NumberMissing;
                        Message = "後三碼必須是數字";
                        break;
                    }
                }
            }

            if (Error != EmpNOErrors.NoError)
            {
                EmpNOCheckEventArgs arg = new EmpNOCheckEventArgs()
                    {
                        Error = Error,
                        Message = Message
                    };

                // 會把 Focus 鎖在 TextBox 內,無法移開
                e.Cancel = true;

                // 觸發事件
               OnEmpNOCheck(arg);
            }
        }
    }
}
[C#] 使用者控制項 Part2-3
  • Windows Form Demo 相關
namespace Demo
{
    public partial class Form1 : Form
    {
        private void employeeNumber_EmpNOCheck(object sender, PKUserControl.EmployeeNumber.EmpNOCheckEventArgs e)
        {
            MessageBox.Show(e.Message, "EmpNOCheck 事件回傳錯誤訊息", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            employeeNumber.ConnectionString = @"Data Source=XXXXX;Initial Catalog=AdventureWorks2014;Integrated Security=True";

            string Text = string.Empty;
            MessageBoxIcon Icon = MessageBoxIcon.None;

            if (employeeNumber.EmpNOCheckDAO())
            {
                Text = "該員工編號已存在,請輸入其他編號";
                Icon = MessageBoxIcon.Error;
            }
            else
            {
                Text = "可以使用該員工編號 ";
                Icon = MessageBoxIcon.Information;
            }

            MessageBox.Show(Text, "員工編號確認", MessageBoxButtons.OK, Icon);
        }
    }
}
  • Attribute 設定
[C#] 使用者控制項 Part2-4
  • Command.ExecuteScalar();
一開始利用 ExecuteScalar() 要接收 Store Procedure 的 Return 值,一直回傳 null,後來查發現 ExecuteScalar() 只會回傳第一筆資料的第一個欄位值,完全搞錯

MSDN 說明
執行查詢,並傳回查詢所傳回的結果集第一個資料列的第一個資料行。 會忽略其他的資料行或資料列。
  • 測試

[C#] 使用者控制項 Part2-5

[C#] 使用者控制項 Part2-6

[C#] 使用者控制項 Part2-7

沒有留言:

張貼留言