簡體   English   中英

如何在 WinForms DataGrid 中繪制所選行的邊框?

[英]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控件派生的自定義控件。

因為,根據評論,情況似乎是這樣,所以沒有太多的工作要做。
使用此處顯示的事件處理程序訂閱PaintScroll事件,這允許沿所選行的邊界繪制一個矩形,考慮到 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 之一(如DataGridTextBoxColumnDataGridBoolColumn或基本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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM