[C#][WinForm]DataGridView的ComboBox型的欄位不能異動DataSource的替代方式,和練習DataRelation

摘要:DataGridView的ComboBox型的欄位不能異動DataSource的替代方式,和練習DataRelation

替代方式的執行畫面如下:

資料庫是NORTHWND,

當點到ProductName欄位時在Form右邊出現關聯該列CtegoryName欄位的ProductName選項們,

使用者可點選ProductName選項替換掉選取的ProductName欄位

 

沒有點選ProductName欄位或CategoryName欄位的Value無值時,隱藏ProductName選項們

這個Form除了將DataGridView,ListBox,SplitContainer拉進Form裡作以下的畫面配置外,

其餘的屬性,事件,宣告等...都寫在.cs檔裡,除了我自己練習外也可讓您清楚所有的設定。

程式如下:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }
        DataSet DataSet_1;
        BindingSource BindingSource_Category;
        BindingSource BindingSource_Product;
        private void Form3_Load(object sender, EventArgs e)
        {
            # region 建立一個DataSet然後加入DataTable_Categories,DataTable_Products資料表並填入資料
            DataTable DataTable_OrderDetails = new DataTable("DataTable_OrderDetails");
            DataTable DataTable_Categories = new DataTable("DataTable_Categories");
            DataTable DataTable_Products = new DataTable("DataTable_Products");
            DataSet_1 = new DataSet();
            DataSet_1.Tables.AddRange(new DataTable[] { DataTable_OrderDetails, DataTable_Categories, DataTable_Products });
            using (SqlConnection SqlConnection_1 = new SqlConnection(WindowsFormsApplication1.Properties.Settings.Default.NORTHWNDConnectionString))
            {
                using (SqlCommand SqlCommand_1 = new SqlCommand())
                {
                    SqlCommand_1.Connection = SqlConnection_1;
                    using (SqlDataAdapter SqlDataAdapter_1 = new SqlDataAdapter(SqlCommand_1))
                    {
                        SqlCommand_1.CommandText =
                          " SELECT top 15 [Order Details].OrderID, Categories.CategoryID, [Order Details].ProductID, Products.ProductName, "
                        + " [Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount "
                        + " FROM [Order Details] INNER JOIN "
                        + " Products ON [Order Details].ProductID = Products.ProductID INNER JOIN "
                        + " Categories ON Products.CategoryID = Categories.CategoryID ";
                        SqlDataAdapter_1.Fill(DataSet_1, "DataTable_OrderDetails");
                        SqlCommand_1.CommandText = "select CategoryID,CategoryName from Categories";
                        SqlDataAdapter_1.Fill(DataSet_1, "DataTable_Categories");
                        SqlCommand_1.CommandText = "select ProductID,ProductName,CategoryID from Products";
                        SqlDataAdapter_1.Fill(DataSet_1, "DataTable_Products");
                    }
                }
            }
            #endregion
            #region 建立DataTable_Categories,DataTable_Products資料表間的關聯,並將控制項綁定資料
            DataRelation DataRelation_1 = new DataRelation("FK_Products_Categories", DataTable_Categories.Columns["CategoryID"], DataTable_Products.Columns["CategoryID"]);
            DataSet_1.Relations.Add(DataRelation_1);
            BindingSource_Category = new BindingSource(DataSet_1, "DataTable_Categories");
            BindingSource_Product = new BindingSource(BindingSource_Category, "FK_Products_Categories");
            #region 建立一個要放在dataGridView1裡的ComboBox型的資料行,換掉dataGridView1設定DataSource後自動產生的CategoryID資料行
            DataGridViewComboBoxColumn categoryNameDataGridViewComboBoxColumn = new DataGridViewComboBoxColumn();
            categoryNameDataGridViewComboBoxColumn.Name = "CategoryID";
            categoryNameDataGridViewComboBoxColumn.DataSource = BindingSource_Category;
            categoryNameDataGridViewComboBoxColumn.ValueMember = "CategoryID";
            categoryNameDataGridViewComboBoxColumn.DisplayMember = "CategoryName";
            categoryNameDataGridViewComboBoxColumn.DataPropertyName = "CategoryID";
            categoryNameDataGridViewComboBoxColumn.HeaderText = "CategoryName";
            dataGridView1.DataSource = DataSet_1.Tables["DataTable_OrderDetails"];
            dataGridView1.Columns.Remove("CategoryID");
            dataGridView1.Columns.Insert(dataGridView1.Columns["OrderID"].Index + 1, categoryNameDataGridViewComboBoxColumn);
            #endregion
            listBox1.DataSource = BindingSource_Product;
            listBox1.ValueMember = "ProductID";
            listBox1.DisplayMember = "ProductName";
            #endregion
            #region 加入操作時的事件
            dataGridView1.CellEnter += new DataGridViewCellEventHandler(dataGridView1_CellEnter);
            listBox1.Click += new EventHandler(listBox1_Click);
            #endregion
            #region 設定一些外觀
            dataGridView1.Columns["OrderID"].ReadOnly = true;
            dataGridView1.Columns["ProductID"].ReadOnly = true;
            dataGridView1.Columns["ProductName"].ReadOnly = true;
            this.WindowState = FormWindowState.Maximized;
            splitContainer1.Dock = DockStyle.Fill;
            dataGridView1.Dock = DockStyle.Fill;
            listBox1.Dock = DockStyle.Fill;
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            #endregion
        }

        void listBox1_Click(object sender, EventArgs e)
        {
            #region 將使用者在listBox1選的Product填入在dataGridView1指定的Product欄位
            dataGridView1.CurrentRow.Cells["ProductID"].Value = ((DataRowView)listBox1.SelectedItem).Row[0];
            dataGridView1.CurrentRow.Cells["ProductName"].Value = ((DataRowView)listBox1.SelectedItem).Row[1];
            #endregion
        }

        void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            #region 若使用者點的不是dataGridView1的Product欄位則將splitContainer1.Panel2收起來,若是則展開並顯示所選的Category的Products
            if (e.ColumnIndex == dataGridView1.Columns["ProductName"].Index && !string.IsNullOrEmpty(dataGridView1.CurrentRow.Cells["CategoryID"].Value.ToString()))
            {
                int FindPosition = BindingSource_Category.Find("CategoryID", dataGridView1.CurrentRow.Cells["CategoryID"].Value);
                BindingSource_Category.Position = FindPosition;
                splitContainer1.Panel2Collapsed = false;
            }
            else
            {
                splitContainer1.Panel2Collapsed = true;
            }
            #endregion
        }
    }
}

如有更好的方式,懇請您指教~