[英]How to paint the border of the selected Row in a WinForms DataGrid?
我有一個從舊的WinForms DataGrid派生的自定義控件。
當用戶單擊它時,我想在所選行周圍繪制一個邊框:行邊框,而不是單元格的邊框,或者更改行的背景顏色等。
就像圖形示例中的行(DataGrid 的第 3 行上的紅線)。
我不希望它像第一行一樣,有藍色背景。
我看到了這個問題:
在編輯 DataGridView 單元格時如何在其周圍繪制邊框?
我無法實現這一點,因為 DataGrid 沒有CellPainting
事件。
嘗試不同的東西,我在.Selected
上有一個錯誤:
if (e.ColumnIndex != -1 &&
e.RowIndex != -1 && dataGridView1[e.ColumnIndex, e.RowIndex].Selected)
此 Grid 看起來像從舊DataGrid控件派生的自定義控件。
因為,根據評論,情況似乎是這樣,所以沒有太多的工作要做。
使用此處顯示的事件處理程序訂閱Paint
和Scroll
事件,這允許沿所選行的邊界繪制一個矩形,考慮到 Scroll 偏移和垂直 ScrollBar 寬度(ScrollBars 是 DataGrid 的子控件,不一定是默認大小,通常由SystemInformation.VerticalScrollBarWidth
返回)。
您可能無法:
DotKasa.Kontrole.MyDataGrid
直接轉換為DataGrid
。 如果不能,請將 DataGrid 控件添加到項目的工具箱中(打開工具箱,在其中右鍵單擊,select Choose Items...
,找到 DataGrid 並勾選它)。base
。將此代碼添加到您的表單中,看看它是如何進行的:
int dataGridPenSize = 3;
private void MyDataGrid_Paint(object sender, PaintEventArgs e)
{
var rect = GetDataGridCurrentRowRect(sender as DataGrid);
if (rect != Rectangle.Empty) {
using (var pen = new Pen(Color.Red, dataGridPenSize)) {
e.Graphics.DrawRectangle(pen, rect);
}
}
}
private void MyDataGrid_Scroll(object sender, EventArgs e)
=> (sender as Control).Invalidate();
private Rectangle GetDataGridCurrentRowRect(DataGrid dg)
{
int scrollbarWidth = GetVerticalScrollBarWidth(dg);
var bounds = dg.GetCurrentCellBounds();
int upperLimit = dg.PreferredRowHeight + (dg.CaptionVisible ? dg.CaptionFont.Height + 4 : 0);
if (bounds.Y <= upperLimit) return Rectangle.Empty;
var rect = new Rectangle (
new Point(dg.RowHeaderWidth, bounds.Y),
new Size(dg.PreferredSize.Width - dg.RowHeaderWidth - dataGridPenSize - scrollbarWidth, bounds.Height));
return rect;
}
private int GetVerticalScrollBarWidth(DataGrid dg) {
var vScroll = dg.Controls.OfType<VScrollBar>().FirstOrDefault();
return vScroll == null ? 0 : vScroll.Width;
}
要完全控制行和列的外觀,您通常需要從現有的內置列 styles 之一(如DataGridTextBoxColumn或DataGridBoolColumn或基本DataGridColumnStyle )驅動來創建自定義列 styles。 然后,您可以通過覆蓋 class 的屬性和方法來自定義行為。
你會發現這篇文章非常有用:
示例 - 為 DataGrid 行繪制邊框
private void Form1_Load(object sender, EventArgs e)
{
var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Rows.Add(1, "A");
dt.Rows.Add(2, "B");
dt.Rows.Add(3, "C");
var dg = new DataGrid();
dg.Dock = DockStyle.Fill;
var ts = new DataGridTableStyle();
ts.GridColumnStyles.Add(new MyDataGridTextBoxColumn()
{ MappingName = "Id", HeaderText = "Id" });
ts.GridColumnStyles.Add(new MyDataGridTextBoxColumn()
{ MappingName = "Name", HeaderText = "Name" });
dg.TableStyles.Add(ts);
this.Controls.Add(dg);
dg.DataSource = dt;
}
public class MyDataGridTextBoxColumn : DataGridTextBoxColumn
{
protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager
source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
{
base.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight);
if (this.DataGridTableStyle.DataGrid.CurrentRowIndex == rowNum)
{
g.DrawLine(Pens.Red, bounds.Left - 1, bounds.Top,
bounds.Right + 1, bounds.Top);
g.DrawLine(Pens.Red, bounds.Left - 1, bounds.Bottom -1 ,
bounds.Right + 1, bounds.Bottom - 1);
}
}
}
我嘗試了一些東西,它幾乎像你想要的那樣工作。
您可以使用此 function 訪問要在其中將邊框塗成紅色的每個單元格的邊界矩形:
dataGridView1.GetCellDisplayRectangle(ColumnIndex, RowIndex, true)
我創建了一個公共矩形列表,我將所有要繪制紅色的單元格邊框矩形放在其中。
public List<Rectangle> rectlist = new List<Rectangle>();
然后我添加了 datagridview_cellclick 事件和 datagridview_paint 事件,並在其中放入以下代碼:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
rectlist.Clear();
for(int i = 0; i < dataGridView1.Columns.Count; i++)
{
rectlist.Add(dataGridView1.GetCellDisplayRectangle(i, e.RowIndex, true));
}
dataGridView1.Refresh();
}
private void dataGridView1_Paint(object sender, PaintEventArgs e)
{
foreach(Rectangle rect in rectlist)
{
e.Graphics.DrawRectangle(Pens.Red, rect);
}
}
每次單擊單元格時,此代碼都會將單元格中的所有單元格邊框矩形放在列表的同一行中。 然后 datagridview.refresh() function 將調用 datagridview_paint function。 在那里,您可以使用painteventargs 在datagridview 上繪制矩形。 這個解決方案唯一的缺點是,每個單元格的整個邊界都被塗成紅色。
它看起來像這樣:帶有紅色邊框的 dgv
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.