簡體   English   中英

如何在winforms的datagridview的當前單元格中添加橢圓按鈕和文本框

[英]how to add ellipse button and textbox in current cell of datagridview in winforms

我想在我的 datagridview 的當前單元格中添加一個橢圓按鈕和文本框控件。 通過單擊橢圓按鈕,我想打開一個自定義計算器,它的結果將顯示在文本框中。 我已經開發了自定義計算器。 我只想在當前選定的單元格中顯示橢圓按鈕和文本框控件。 如果我離開一個單元格,那么文本框控件的值應該分配給已經離開的單元格。 以下是截圖。

在此處輸入圖片說明

在此處輸入圖片說明

您需要創建自定義EditingControlCellColumn類,如下所述: http : //msdn.microsoft.com/en-us/library/aa730881( EditingControl .aspx

我已經為您創建了示例應用程序。 請參閱下面的下載鏈接。
內容:

  • 文本按鈕控件
    UserControl 包含無邊框和簡單按鈕的 TextBox。
    在此處輸入圖片說明

  • 簡單的編輯表格
    任何簡單的對話框形式,返回DialogResult
    在此處輸入圖片說明

  • DataGridViewTextButtonEditingControl
    我們需要從我們的TextButton控件繼承並在這里實現IDataGridViewEditingControl接口。

     internal class DataGridViewTextButtonEditingControl : TextButton, IDataGridViewEditingControl { public DataGridViewTextButtonEditingControl() { InnerTextBox.TextChanged += (o, e) => NotifyDataGridViewOfValueChange(); } public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) { Font = dataGridViewCellStyle.Font; if (dataGridViewCellStyle.BackColor.A < 255) { Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor); BackColor = opaqueBackColor; EditingControlDataGridView.EditingPanel.BackColor = opaqueBackColor; } else { BackColor = dataGridViewCellStyle.BackColor; } ForeColor = dataGridViewCellStyle.ForeColor; } public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey) { TextBox textBox = InnerTextBox; switch (keyData & Keys.KeyCode) { case Keys.Right: { if (textBox != null) { // If the end of the selection is at the end of the string, // let the DataGridView treat the key message if ((RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length)) || (RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0))) { return true; } } break; } case Keys.Left: { if (textBox != null) { // If the end of the selection is at the begining of the string // or if the entire text is selected and we did not start editing, // send this character to the dataGridView, else process the key message if ((RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0)) || (RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length))) { return true; } } break; } case Keys.Home: case Keys.End: { // Let the grid handle the key if the entire text is selected. if (textBox != null) { if (textBox.SelectionLength != textBox.Text.Length) { return true; } } break; } case Keys.Delete: { // Let the grid handle the key if the carret is at the end of the text. if (textBox != null) { if (textBox.SelectionLength > 0 || textBox.SelectionStart < textBox.Text.Length) { return true; } } break; } } return !dataGridViewWantsInputKey; } public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) { return Text; // Convert.ChangeType(Text, typeof(int)); } public void PrepareEditingControlForEdit(bool selectAll) { if (selectAll) { InnerTextBox.SelectAll(); } else { // Do not select all the text, but // position the caret at the end of the text InnerTextBox.SelectionStart = InnerTextBox.Text.Length; } } public DataGridView EditingControlDataGridView { get; set; } public object EditingControlFormattedValue { get; set; } public int EditingControlRowIndex { get; set; } public bool EditingControlValueChanged { get; set; } public Cursor EditingPanelCursor { get; private set; } public bool RepositionEditingControlOnValueChange { get; private set; } protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); NotifyDataGridViewOfValueChange(); } private void NotifyDataGridViewOfValueChange() { if (!EditingControlValueChanged) { EditingControlValueChanged = true; EditingControlDataGridView.NotifyCurrentCellDirty(true); } } }
  • DataGridViewTextButtonCell
    我們需要從DataGridViewCell繼承來實現DataGridViewTextButtonEditingControl初始化、單元格繪制和(重要的!)克隆。
    如果不覆蓋Clone()方法,我們將無法設置新創建的實例的屬性。

     internal sealed class DataGridViewTextButtonCell : DataGridViewCell { private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetLeft = 3; private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetRight = 4; private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft = 0; private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight = 0; private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetTop = 2; private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetBottom = 1; private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping = 1; private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping = 2; private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom = 1; // Type of this cell's editing control private static readonly Type defaultEditType = typeof(DataGridViewTextButtonEditingControl); // Type of this cell's value. The formatted value type is string, the same as the base class DataGridViewTextBoxCell private static readonly Type defaultValueType = typeof(string); public override object Clone() { DataGridViewTextButtonCell cell = base.Clone() as DataGridViewTextButtonCell; if (cell != null) { cell.ButtonClickHandler = ButtonClickHandler; } return cell; } /// <summary> /// Adjusts the location and size of the editing control given the alignment characteristics of the cell /// </summary> private Rectangle GetAdjustedEditingControlBounds(Rectangle editingControlBounds, DataGridViewCellStyle cellStyle) { // Add a 1 pixel padding on the left and right of the editing control editingControlBounds.X += 1; editingControlBounds.Width = Math.Max(0, editingControlBounds.Width - 2); // Adjust the vertical location of the editing control: int preferredHeight = cellStyle.Font.Height + 3; if (preferredHeight < editingControlBounds.Height) { switch (cellStyle.Alignment) { case DataGridViewContentAlignment.MiddleLeft: case DataGridViewContentAlignment.MiddleCenter: case DataGridViewContentAlignment.MiddleRight: editingControlBounds.Y += (editingControlBounds.Height - preferredHeight) / 2; break; case DataGridViewContentAlignment.BottomLeft: case DataGridViewContentAlignment.BottomCenter: case DataGridViewContentAlignment.BottomRight: editingControlBounds.Y += editingControlBounds.Height - preferredHeight; break; } } return editingControlBounds; } public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); TextButton textButton = DataGridView.EditingControl as TextButton; if (textButton != null) { //textButton.BorderStyle = BorderStyle.None; string initialFormattedValueStr = initialFormattedValue as string; textButton.Text = initialFormattedValueStr; if (ButtonClickHandler != null) textButton.ButtonClick += ButtonClickHandler; } } public override void DetachEditingControl() { base.DetachEditingControl(); TextButton textButton = DataGridView.EditingControl as TextButton; if (textButton != null) { textButton.ClearUndo(); if (ButtonClickHandler != null) textButton.ButtonClick -= ButtonClickHandler; } } public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { Rectangle editingControlBounds = PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow); editingControlBounds = GetAdjustedEditingControlBounds(editingControlBounds, cellStyle); DataGridView.EditingControl.Location = new Point(editingControlBounds.X, editingControlBounds.Y); DataGridView.EditingControl.Size = new Size(editingControlBounds.Width, editingControlBounds.Height); } public DataGridViewTextButtonEditingControl EditingControl { get { return DataGridView == null ? null : DataGridView.EditingControl as DataGridViewTextButtonEditingControl; } } public override Type EditType { get { return defaultEditType; } } public override Type ValueType { get { return base.ValueType ?? defaultValueType; } } public override Type FormattedValueType { get { return defaultValueType; } } protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { if (DataGridView == null) { return; } // First paint the borders and background of the cell. base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts & ~(DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.ContentForeground)); //if (PartPainted(paintParts, DataGridViewPaintParts.Border)) // PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle); Point ptCurrentCell = DataGridView.CurrentCellAddress; bool cellCurrent = ptCurrentCell.X == ColumnIndex && ptCurrentCell.Y == rowIndex; bool cellEdited = cellCurrent && DataGridView.EditingControl != null; // If the cell is in editing mode, there is nothing else to paint if (cellEdited) { if (PartPainted(paintParts, DataGridViewPaintParts.Background)) { //graphics.FillRectangle(br, cellBounds); PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle); } } else { if (PartPainted(paintParts, DataGridViewPaintParts.ContentForeground)) { // Take the borders into account Rectangle borderWidths = BorderWidths(advancedBorderStyle); Rectangle valBounds = cellBounds; valBounds.Offset(borderWidths.X, borderWidths.Y); valBounds.Width -= borderWidths.Right; valBounds.Height -= borderWidths.Bottom; // Also take the padding into account if (cellStyle.Padding != Padding.Empty) { if (DataGridView.RightToLeft == RightToLeft.Yes) { valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top); } else { valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top); } valBounds.Width -= cellStyle.Padding.Horizontal; valBounds.Height -= cellStyle.Padding.Vertical; } valBounds = GetAdjustedEditingControlBounds(valBounds, cellStyle); TextFormatFlags horAlign = TextFormatFlags.Left; switch (cellStyle.Alignment) { case DataGridViewContentAlignment.BottomLeft: case DataGridViewContentAlignment.MiddleLeft: case DataGridViewContentAlignment.TopLeft: horAlign = TextFormatFlags.Left; break; case DataGridViewContentAlignment.BottomCenter: case DataGridViewContentAlignment.MiddleCenter: case DataGridViewContentAlignment.TopCenter: horAlign = TextFormatFlags.HorizontalCenter; break; case DataGridViewContentAlignment.BottomRight: case DataGridViewContentAlignment.MiddleRight: case DataGridViewContentAlignment.TopRight: horAlign = TextFormatFlags.Right; break; } bool cellSelected = (cellState & DataGridViewElementStates.Selected) != 0; SolidBrush br = new SolidBrush(cellSelected ? cellStyle.SelectionBackColor : cellStyle.BackColor); if (PartPainted(paintParts, DataGridViewPaintParts.Background)) { graphics.FillRectangle(br, cellBounds); PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle); } if (cellStyle.Padding != Padding.Empty) { valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top); valBounds.Width -= cellStyle.Padding.Horizontal; valBounds.Height -= cellStyle.Padding.Vertical; } if (cellCurrent) { // Draw focus rectangle if (DataGridView.Focused && valBounds.Width > 0 && valBounds.Height > 0) { ControlPaint.DrawFocusRectangle(graphics, valBounds, Color.Empty, br.Color); } } int verticalTextMarginTop = cellStyle.WrapMode == DataGridViewTriState.True ? DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping : DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping; valBounds.Offset(DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft, verticalTextMarginTop); valBounds.Width -= DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft + DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight; valBounds.Height -= verticalTextMarginTop + DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom; TextRenderer.DrawText(graphics, formattedValue as string, cellStyle.Font, valBounds, cellSelected ? cellStyle.SelectionForeColor : cellStyle.ForeColor, TextFormatFlags.Default | horAlign | TextFormatFlags.Top); } if (PartPainted(paintParts, DataGridViewPaintParts.ErrorIcon)) { // Paint the potential error icon on top of the NumericUpDown control base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, DataGridViewPaintParts.ErrorIcon); } } } /// <summary> /// Little utility function called by the Paint function to see if a particular part needs to be painted. /// </summary> private static bool PartPainted(DataGridViewPaintParts paintParts, DataGridViewPaintParts paintPart) { return (paintParts & paintPart) != 0; } public EventHandler<TextButton.TextButtonEventArgs> ButtonClickHandler { get; set; } }
  • DataGridViewTextButtonColumn
    簡單地從DataGridViewColumn繼承並提供幾個應該傳遞給我們底層TextButton控件的屬性。

     internal sealed class DataGridViewTextButtonColumn : DataGridViewColumn { private EventHandler<TextButton.TextButtonEventArgs> buttonClickHandler; public DataGridViewTextButtonColumn() : base(new DataGridViewTextButtonCell()) { } public EventHandler<TextButton.TextButtonEventArgs> ButtonClickHandler { get { return buttonClickHandler; } set { DataGridViewTextButtonCell cell = CellTemplate as DataGridViewTextButtonCell; if (cell != null) { if (value != null) cell.ButtonClickHandler += value; else if (buttonClickHandler != null) cell.ButtonClickHandler -= buttonClickHandler; } buttonClickHandler = value; } } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { base.CellTemplate = value; DataGridViewTextButtonCell cell = CellTemplate as DataGridViewTextButtonCell; if (cell != null) cell.ButtonClickHandler = ButtonClickHandler; } } }
  • 使用示例
    假設gridDataGridView

     grid.Columns.AddRange(new DataGridViewColumn[] { new DataGridViewTextBoxColumn { ValueType = typeof (string), HeaderText = "Name" }, new DataGridViewTextButtonColumn { ValueType = typeof (int), HeaderText = "Count", ButtonClickHandler = (o, e) => { grid.EndEdit(); using (EditForm frm = new EditForm { Value = e.Text }) if (frm.ShowDialog(this) == DialogResult.OK) { e.Text = frm.Value; e.Handled = true; } grid.BeginEdit(false); } } });

下載鏈接: 完整項目(Zip-Archive,目標框架:v.3.5)
更新(21 年 4 月 2 日) :鏈接已修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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