星期二, 12月 09, 2014

[ADO.NET] 計算 DataTable 資料筆數

論壇問題
從 Database 中把 DataTable 後,把重覆值去除掉後當成 comboBox 資料來源,希望點選 comboxBox 時,可以顯示該選項在 DataTable 內的資料筆數
想法是利用 T-SQL DISTINCT 語法找出唯一値當成 comboxBox 資料來源,再根據使用者點選資料,進入 Database 計算資料筆數,論壇討論則是把資料通通抓到 C# 中來處理,剛好拿來練習 ADO.NET
namespace ComboBoxSearch
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // dtCombo 為全域變數
        DataTable dtCombo = new DataTable("Demo");

        private void Form1_Load(object sender, EventArgs e)
        {
            // 資料來源建立
            sourceFill();

            // 設定 ComboBox 的 DropDownStyle 
            cboList.DropDownStyle = ComboBoxStyle.DropDownList;
            cboDataTable.DropDownStyle = ComboBoxStyle.DropDownList;
            // 設定 ComboBox 一開始不顯示任何選項
            cboList.SelectedIndex = -1;
            cboDataTable.SelectedIndex = -1;
            // 不允許 DataGridView 可以新增資料
            gvData.AllowUserToAddRows = false;
        }

        private void sourceFill()
        {
            // dtCombo Schema 和 Data 建立
            dtCombo.Columns.Add("ColName",typeof(string));
            dtCombo.Rows.Add("A");
            dtCombo.Rows.Add("A");
            dtCombo.Rows.Add("A");
            dtCombo.Rows.Add("B");
            dtCombo.Rows.Add("B");
            dtCombo.Rows.Add("C");
            dtCombo.Rows.Add("C");
            dtCombo.Rows.Add("C");
            dtCombo.Rows.Add("C");
            dtCombo.Rows.Add("D");
            dtCombo.Rows.Add("D");
            dtCombo.Rows.Add("D");
            dtCombo.Rows.Add("D");
            dtCombo.Rows.Add("D");

            // 資料來源為 List
            List<string> uniqueLINQ = dtCombo.AsEnumerable().Select(row => row.Field<string>("ColName")).Distinct().ToList();
            cboList.DataSource = uniqueLINQ;

            // 資料來源為 DataTable
            DataTable uniqueDataTable = dtCombo.DefaultView.ToTable(true, "ColName");
            cboDataTable.DataSource = uniqueDataTable;
            cboDataTable.ValueMember = "ColName";
            cboDataTable.DisplayMember = "ColName";

            // 把 dtCombo 資料顯示出來,方便比對資料
            gvData.DataSource = dtCombo;
        }

        private void gvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (!gvData.Columns[e.ColumnIndex].Name.Equals("ColName")) return;

            string item =
                cboList.SelectedIndex == -1
                ? string.Empty
                : cboList.SelectedItem.ToString();
   
            string value = 
                cboDataTable.SelectedIndex == -1
                ? string.Empty
                : cboDataTable.SelectedValue.ToString();

            e.CellStyle.BackColor = SystemColors.Control;
            if (e.Value.ToString() == item || e.Value.ToString() == value) 
              e.CellStyle.BackColor = Color.LightGray;
        }

        private void cboList_SelectionChangeCommitted(object sender, EventArgs e)
        {
            // LINQ 作法
            if (cboList.SelectedIndex == -1) return;
            string item = cboList.SelectedItem.ToString();

            string result = dtCombo.AsEnumerable().Where(row => row.Field<string>("ColName") == item).Count().ToString();

            txtList.Text = result;
            gvData.Refresh();
        }

        private void cboDataTable_SelectionChangeCommitted(object sender, EventArgs e)
        {
            // ADO.NET 作法
            if (cboDataTable.SelectedIndex == -1) return;
            string value = cboDataTable.SelectedValue.ToString();

            string filter = string.Format("ColName = '{0}'", value);
            string result = dtCombo.Compute("COUNT(ColName)", filter).ToString();

            txtDataTable.Text = result;
            gvData.Refresh();
        }
    }
}

練習時發現,當 Form 一執行時都會觸發 ComboBox SelectedIndexChanged 事件,在 MSDN ComboBox.SelectionChangeCommitted 事件,看見這段說明
只有當使用者變更下拉式方塊選擇時,才會引發 SelectionChangeCommitted。 請勿使用 SelectedIndexChanged 或 SelectedValueChanged 來擷取使用者變更,因為當以程式方式變更選擇時,也會引發這些事件。
ComboBox 預設點擊事件為 SelectedIndexChanged,所以也就很直覺地把 Code 寫在裡面,Orz ~~

沒有留言:

張貼留言