Project
- Form1 是主 Form
- Form2 用來顯示明細資料
- DataSource.Script 內有用到的 Sample Data 和 Store Prodecure
Layout
- Form1:一個 DataGridView
- Form2:如下圖,DataGridView + ToolStripStatusLabel
DataSource Script - 建立資料來練習
-- DROP XXX IF EXISTS 為 SQL Server 2016 新語法
DROP DATABASE IF EXISTS Demo
CREATE DATABASE Demo
GO
USE Demo
GO
DROP TABLE IF EXISTS Product
CREATE TABLE Product (ProdID int , ProdName nchar(50) , ProdURL char(100))
INSERT INTO Product VALUES
(1,'SQL Server','https://www.microsoft.com/en-us/cloud-platform/sql-server'),
(2,'Wndows Server','https://www.microsoft.com/en-us/cloud-platform/windows-server-2016'),
(3,'Visual Studio','https://www.visualstudio.com/')
GO
DROP TABLE IF EXISTS ProductDetail
CREATE TABLE ProductDetail (ID int IDENTITY(1,1), ProdID int , DetailName nchar(50))
INSERT INTO ProductDetail VALUES
(1,'SQL Server 2016'),
(1,'SQL Server 2014'),
(1,'SQL Server 2012'),
(1,'SQL Server 2008'),
(1,'SQL Server 2005'),
(2,'Windows Server 2016'),
(2,'Windows Server 2012'),
(2,'Windows Server 2008'),
(2,'Windows Server 2003'),
(2,'Windows Server 2000'),
(3,'Visual Studio 2015'),
(3,'Visual Studio 2013'),
(3,'Visual Studio 2012'),
(3,'Visual Studio 2010'),
(3,'Visual Studio 2008')
GO
DROP PROCEDURE IF EXISTS uspProduct
GO
CREATE PROCEDURE uspProduct
AS
BEGIN
SELECT
ProdID ,
ProdName ,
ProdURL
FROM Demo.dbo.Product
END
GO
DROP PROCEDURE IF EXISTS uspProductDetailByProdID
GO
CREATE PROCEDURE uspProductDetailByProdID(@ProdID int)
AS
BEGIN
SELECT
DetailName
FROM Demo.dbo.ProductDetail
WHERE ProdID = @ProdID
END
GO
Form1.cs
using System.Data.SqlClient;
using System.Diagnostics;
namespace DGVSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.AutoGenerateColumns = false;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Dock = DockStyle.Fill;
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "ProdID", Name = "ColProdID", HeaderText = "產品編號", Width = 100, Visible = true });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "ProdName", Name = "ColProdName", HeaderText = "產品名稱", Width = 100, Visible = true, AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells });
// 採取把 URL 塞在一個看不見 Column 內,也可以點選後進 DataTable 內抓網站連結
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "ProdURL",
Name = "ColProdURL",
HeaderText = "產品官方網站連結",
Width = 100,
Visible = false
});
dataGridView1.Columns.Add(new DataGridViewLinkColumn
{
DataPropertyName = "",
Name = "ColURL",
HeaderText = "產品官方網站連結",
Text = "連結網址",
Width = 100,
Visible = true,
AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader,
UseColumnTextForLinkValue = true,
});
dataGridView1.Columns.Add(new DataGridViewLinkColumn
{
DataPropertyName = "",
Name = "ColProductDetail",
HeaderText = "",
Text = "明細資料",
Width = 100,
Visible = true,
AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader,
UseColumnTextForLinkValue = true,
});
dataGridView1.DataSource = GetProductData();
dataGridView1.CellContentClick += DataGridView1_CellContentClick;
dataGridView1.KeyDown += DataGridView1_KeyDown;
}
private void ShowDetail(int ProdID)
{
Form2 frmDetail = new Form2();
frmDetail.ShowDialog(
GetProdName(ProdID),
GetProductDetailData(ProdID));
}
private string GetProdName(int ProdID)
{
string ProdName = string.Empty;
DataGridViewRow row = dataGridView1.Rows.OfType<DataGridViewRow>()
.Where(r => (int)r.Cells["ColProdID"].Value == ProdID)
.First();
if (row == null) return ProdName;
ProdName = row.Cells["ColProdName"].Value.ToString().Trim();
return ProdName;
}
#region DataGridView Event
private void DataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Enter) return;
// 抓 DataGridView Cell 值方法
// 方法一
// int ProdID = (int)dataGridView1.CurrentRow.Cells["ColProdID"].Value;
// 方法二
int ProdID = (int)dataGridView1.Rows[dataGridView1.CurrentCellAddress.Y].Cells["ColProdID"].Value;
ShowDetail(ProdID);
}
private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;
DataGridView dgv = sender as DataGridView;
if (e.ColumnIndex == dgv.Columns["ColURL"].Index)
{
Process.Start(dataGridView1.Rows[e.RowIndex].Cells["ColProdURL"].Value.ToString());
}
if (e.ColumnIndex == dgv.Columns["ColProductDetail"].Index)
{
int ProdID = (int)dgv.Rows[e.RowIndex].Cells["ColProdID"].Value;
ShowDetail(ProdID);
}
}
#endregion
#region 資料庫存取相關
private string ConnectionString = @"Data Source=.\SQL2016;Initial Catalog=Demo;Integrated Security=True";
private DataTable GetProductData()
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
try
{
SqlCommand cmd = new SqlCommand("uspProduct", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
catch (Exception)
{
throw;
}
}
}
private DataTable GetProductDetailData(int ProdID)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
try
{
SqlCommand cmd = new SqlCommand("uspProductDetailByProdID", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ProdID", SqlDbType.Int).Value = ProdID;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
catch (Exception)
{
throw;
}
}
}
#endregion
}
}
Form2.csnamespace DGVSample
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
dataGridView1.AutoGenerateColumns = false;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.Dock = DockStyle.Fill;
dataGridView1.DataBindingComplete += DataGridView1_DataBindingComplete;
dataGridView1.KeyUp += DataGridView1_KeyUp;
dataGridView1.CellContentClick += DataGridView1_CellContentClick;
dataGridView1.KeyDown += DataGridView1_KeyDown;
dataGridView1.RowPostPaint += DataGridView1_RowPostPaint;
dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn
{
DataPropertyName = "",
Name = "ColChecked",
HeaderText = "勾選",
Width = 100,
Visible = true
});
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "DetailName",
Name = "ColDetailName",
HeaderText = "產品明細名稱",
Width = 100,
Visible = true,
ReadOnly = true
});
}
private void DataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
((DataGridView)sender).AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
public void ShowDialog(string ProdName, DataTable dt)
{
dataGridView1.DataSource = dt;
Text = $"{ProdName} 明細資料";
UpdateStatus();
this.ShowDialog();
}
private void DataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
// 在 RowHeader 標記資料序號
using (SolidBrush b = new SolidBrush(dataGridView1.RowHeadersDefaultCellStyle.ForeColor))
{
e.Graphics.DrawString(
(e.RowIndex + 1).ToString(System.Globalization.CultureInfo.CurrentUICulture),
e.InheritedRowStyle.Font,
b,
e.RowBounds.Location.X + 20,
e.RowBounds.Location.Y + 4);
}
}
private void DataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Space) return;
// 按 Space 鍵可以勾選 CheckBox
// 測試時發現,一進入該 Form 時,Focus 是在 ColChecked Column 的 Cell 上,
// 此時按 Space,會同時觸發 KeyDown 和 CellContentClick Event
// 即使是在 SelectionMode = FullRowSelect 狀態下,Focus 還是用 Cell,而不是整筆 Row
DataGridViewCell cell = dataGridView1.CurrentRow.Cells["ColChecked"];
cell.Value = cell.Value == null ? true : !((bool)cell.Value);
}
private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;
DataGridView dgv = sender as DataGridView;
if (e.ColumnIndex != dgv.Columns["ColChecked"].Index) return;
UpdateStatus();
}
private void DataGridView1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
this.Close();
}
private void UpdateStatus()
{
int CheckedCount = dataGridView1.Rows.OfType<DataGridViewRow>().Where(r => (bool)r.Cells["ColChecked"].EditedFormattedValue == true).Count();
toolStripStatusLabel1.Text = $"使用者勾選 {CheckedCount} 筆資料";
}
}
}
沒有留言:
張貼留言