首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

DataGridColumnStyle 重寫實作:自訂資料格編輯控制項

     編輯:關於C語言

前言

Windows Forms DataGrid 預設資料格編輯控制項功能有限。透過繼承 DataGridColumnStyle 並覆寫關鍵方法,可在資料格中嵌入任意控制項(如下拉清單、日期選擇器、自訂文字方塊),大幅擴展表格編輯體驗。本文以自訂 XP_TextBox 與 DataGridTextBoxColumnStyle 為例,示範完整實作流程。

步驟一:建立自訂編輯控制項

繼承 TextBox,加入禁用貼上、禁用右鍵選單等功能,並覆寫 WndProc 攔截訊息:


public class XP_TextBox : TextBox {
    private bool _enablePaste = true;
    private bool _enableContextMenu = true;

    public bool EnablePaste {
        get { return _enablePaste; }
        set { _enablePaste = value; Invalidate(); }
    }
    public bool EnableContextMenu {
        get { return _enableContextMenu; }
        set { _enableContextMenu = value; Invalidate(); }
    }

    protected override void WndProc(ref Message m) {
        const int WM_PASTE = 0x302;
        const int WM_CONTEXTMENU = 0x7B;
        switch (m.Msg) {
            case WM_PASTE:
                OnPasteEvent();
                if (!_enablePaste) return;
                break;
            case WM_CONTEXTMENU:
                if (!_enableContextMenu) return;
                break;
        }
        base.WndProc(ref m);
    }

    public event EventHandler PasteEvent;
    protected virtual void OnPasteEvent() {
        PasteEvent?.Invoke(this, EventArgs.Empty);
    }
}

步驟二:實作自訂 ColumnStyle

繼承 DataGridColumnStyle,核心覆寫方法:

方法用途
Edit進入編輯模式,顯示編輯控制項並設定初始值
Paint繪製非編輯狀態的資料格外觀
Commit認可編輯值回資料來源
GetPreferredSize / GetPreferredHeight / GetMinimumHeight計算資料格尺寸
Abort取消編輯,隱藏控制項

關鍵實作片段


public class DataGridTextBoxColumnStyle : DataGridColumnStyle {
    private readonly XP_TextBox _textBox = new XP_TextBox();
    private bool _isEditing;
    private int _editingRow = -1;
    private string _oldValue;

    public DataGridTextBoxColumnStyle() {
        _textBox.Visible = false;
        _textBox.BorderStyle = BorderStyle.None;
        _textBox.KeyPress += OnKeyPress;
        _textBox.Leave += OnLeave;
    }

    protected override void Edit(CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string displayText, bool cellIsVisible) {
        _editingRow = rowNum;
        _oldValue = displayText;
        _textBox.Text = displayText;
        _textBox.Bounds = new Rectangle(bounds.X + 2, bounds.Y + 2, bounds.Width - 4, bounds.Height - 4);
        _textBox.Visible = true;
        _textBox.Focus();
        _isEditing = true;
    }

    protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum) {
        Paint(g, bounds, source, rowNum, false);
    }

    protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight) {
        string text = GetColumnValueAtRow(source, rowNum)?.ToString() ?? "";
        Brush backBrush = new SolidBrush(DataGridTableStyle.BackColor);
        Brush foreBrush = new SolidBrush(DataGridTableStyle.ForeColor);
        g.FillRectangle(backBrush, bounds);
        g.DrawString(text, DataGridTableStyle.DataGrid.Font, foreBrush, bounds.X + 2, bounds.Y + 2);
    }

    protected override bool Commit(CurrencyManager dataSource, int rowNum) {
        if (!_isEditing) return false;
        string newValue = _textBox.Text;
        if (newValue != _oldValue) {
            SetColumnValueAtRow(dataSource, rowNum, newValue);
            _oldValue = newValue;
        }
        _isEditing = false;
        _textBox.Visible = false;
        return true;
    }

    protected override void Abort(int rowNum) {
        _isEditing = false;
        _textBox.Visible = false;
    }

    protected override Size GetPreferredSize(Graphics g, object value) {
        return new Size(50, _textBox.PreferredHeight + 2);
    }
    // GetPreferredHeight, GetMinimumHeight 類似
}

步驟三:套用至 DataGrid


DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "Customers";
var colStyle = new DataGridTextBoxColumnStyle();
colStyle.MappingName = "CompanyName";
colStyle.HeaderText = "公司名稱";
colStyle.Width = 200;
tableStyle.GridColumnStyles.Add(colStyle);
dataGrid.TableStyles.Add(tableStyle);

擴展方向

  • 建立 DataGridComboBoxColumnStyle 內嵌 ComboBox 實現下拉選擇。
  • 建立 DataGridDateTimeColumnStyle 內嵌 DateTimePicker。
  • 建立 DataGridCheckBoxColumnStyle 內嵌 CheckBox。
  • 實作 IDataGridEditingControl 介面讓自訂控制項支援更豐富的編輯協定(.NET 2.0+)。

總結

重寫 DataGridColumnStyle 是自訂 DataGrid 資料格編輯體驗的核心技術。掌握 Edit、Paint、Commit、Abort 四大生命週期方法,即可將任意 Windows Forms 控制項無縫整合進資料格,滿足多樣化的業務編輯需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved