问题描述
我想在我的datagridview的当前单元格添加一个椭圆形按钮和文本框控件。通过点击省略号按钮,我想打开一个自定义的计算器,它的结果将在文本框中显示。我已经开发定制的计算器。我只是想表明当前选中的单元格椭圆形按钮和文本框控件。如果我离开一个单元格,然后TextBox控件的值应分配给已lefted细胞。以下是截图。
i want to add an ellipse button and textbox control in current cell of my datagridview. By clicking on ellipse button i want to open a custom calculator and result of it will show in textbox. I have already develop custom calculator. I just want to show ellipse button and textbox control in current selected cell. If i leave a cell, then value of textbox control should assign to cell which has lefted. Following is the screenshot.
推荐答案
您需要创建自定义使用编辑
,细胞
和列
类如下所述:http://msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx
You need to create custom EditingControl
, Cell
and Column
classes as described here: http://msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx
我已经为您创建示例应用程序。参见下面的下载链接。结果
内容:
I've created sample application for you. See download link below.
Contents:
-
TEXT按钮控制结果
用户控件包含无边框和简单的按钮文本框。结果
TextButton control
UserControl containing TextBox without border and simple button.
简单的编辑表单结果
任何简单的对话形式,返回的DialogResult
。结果
Simple Edit Form
Any simple dialog form, returning DialogResult
.
DataGridViewTextButtonEditingControl 类结果
我们需要从我们的 TEXT按钮
控件继承并在这里实施 IDataGridViewEditingControl
接口。
DataGridViewTextButtonEditingControl class
We need to inherit from our TextButton
control and to implement IDataGridViewEditingControl
interface here.
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
初始化,细胞绘画和(重要!)克隆。结果
如果不重写克隆()
方法,我们将不能够设置一个新创建的实例的属性。
DataGridViewTextButtonCell class
We need to inherit from the DataGridViewCell
to implement DataGridViewTextButtonEditingControl
initialization, cell painting and (important!) cloning.
Without overriding the Clone()
method, we will not be able to set properties of a newly created instances.
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 类结果
只需从应传递给我们的基本 TEXT按钮
控制的DataGridViewColumn
并提供几个属性继承。
DataGridViewTextButtonColumn class
Simply inherit from the DataGridViewColumn
and provide several properties that should be passed to the our underlying TextButton
control.
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;
}
}
}
使用示例结果
假设电网
是 DataGridView的
。
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-存档,目标框架:v.3.5)
Download Link: Full project (Zip-Archive, Target Framework: v.3.5)
这篇关于如何添加在的WinForms DataGridView中的当前单元格的椭圆形按钮和文本框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!