我想向DataGridViewColumn
中添加自定义DataGridView
。此列应每行创建以下单元格
首先,我创建了一个自定义UserControl
,该按钮创建了一个带有按钮的标签。
private class AllocationControl : UserControl
{
public AllocationControl(IndexField[] indexFields, BatchField[] batchFields)
{
Label lbl = new Label();
Controls.Add(lbl);
ContextMenuStrip contextMenu = new ContextMenuStrip();
// fill the menu
Controls.Add(contextMenu);
Button btn = new Button();
btn.Click += (object sender, EventArgs e) =>
{
contextMenu.Show(Cursor.Position);
};
Controls.Add(btn);
}
public string DisplayedName { get; private set; }
public double SelectedID { get; private set; }
}
我必须传递一些数据作为构造函数参数,但这与问题无关。
此后,我创建了一个自定义DataGridViewCell
private class DataGridViewAllocationCell : DataGridViewCell
{
public DataGridViewAllocationCell()
{
}
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)
{
AllocationControl allocationControl = value as AllocationControl;
Bitmap allocationControlImage = new Bitmap(cellBounds.Width, cellBounds.Height);
allocationControl.DrawToBitmap(allocationControlImage, new Rectangle(0, 0, allocationControl.Width, allocationControl.Height));
graphics.DrawImage(allocationControlImage, cellBounds.Location);
}
}
此单元格应保留并显示自定义控件。
最后,我通过设置DataGridViewColumn
CellTemplate
中
private class DataGridViewAllocationColumn : DataGridViewColumn
{
public DataGridViewAllocationColumn()
{
CellTemplate = new DataGridViewAllocationCell();
}
}
我的问题是如何将UserControl
分配给DataGridViewCell
?
我接受了本指南
但是它们都显示了如何创建单个控件并将其放入单元格中。我必须在一个单元格内设置三个控件(标签,按钮和contextMenu)。
答案 0 :(得分:1)
对于一种新的列类型,有3个主要支柱:
DataGridViewColumn
负责在控件的列编辑器中的设计模式下设置的属性。 DataGridViewCell
负责单元的外观。它将值和其他绘画部分渲染到单元格中,并初始化编辑控件(如果该列具有任何编辑控件)。 DataGridViewEditingControl
负责编辑单元格的值。 创建新列时,可以从DataGridViewColumn
或其派生类之一派生。同样,在为该列创建新单元格时,您可以从DataGridViewCell
或其派生类之一派生。同样,在创建新的编辑控件时,可以从现有的编辑控件之一派生,也可以从控件类派生并实现IDataGridViewEditingControl
接口开始。
请记住,编辑控件将仅显示在编辑单元格中。其余单元格显示您使用单元格的paint方法渲染的内容。
示例
在本文中,我分享了一个绘制包含标签和按钮的自定义单元格的示例。我尚未创建编辑控件,因为在此示例中,我们可以从DataGridViewButtonColumn
和DataGridViewButtonCell
派生而无需创建编辑控件。我们只是向列添加一些属性,并更改绘制逻辑并覆盖OnContentClick
以显示上下文菜单,如下所示:
自定义列具有LabelText
和ButtonText
属性。当您单击按钮部分时,它将显示您分配给相应属性的ContextMenuStrip
。
注意:这只是一个示例,根据要求,您可能需要更改属性,渲染逻辑和菜单显示方式 或其他任何东西。但是我认为这是一个很好的起点。
代码如下:
using System.Drawing;
using System.Windows.Forms;
public class DataGridViewAllocationControlColumn : DataGridViewButtonColumn
{
public DataGridViewAllocationControlColumn()
{
this.CellTemplate = new DataGridViewAllocationControlCell();
}
public string LabelText { get; set; }
public string ButtonText { get; set; }
public override object Clone()
{
var c = (DataGridViewAllocationControlColumn)base.Clone();
c.LabelText = this.LabelText;
c.ButtonText = this.ButtonText;
return c;
}
}
public class DataGridViewAllocationControlCell : DataGridViewButtonCell
{
protected override void Paint(Graphics graphics, Rectangle clipBounds,
Rectangle cellBounds, int rowIndex,
DataGridViewElementStates elementState,
object value, object formattedValue, string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
var g = this.DataGridView;
var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState,
value, formattedValue, errorText, cellStyle, advancedBorderStyle,
DataGridViewPaintParts.All &
~DataGridViewPaintParts.ContentBackground &
~DataGridViewPaintParts.ContentForeground);
var r1 = g.GetCellDisplayRectangle(c.Index, rowIndex, false);
var r2 = GetContentBounds(rowIndex);
var r3 = new Rectangle(r1.Location, new Size(GetLabelWidth(), r1.Height));
r2.Offset(r1.Location);
base.Paint(graphics, clipBounds, r2, rowIndex, elementState,
value, c.ButtonText, errorText, cellStyle, advancedBorderStyle,
DataGridViewPaintParts.All);
TextRenderer.DrawText(graphics, c.LabelText, cellStyle.Font,
r3, cellStyle.ForeColor);
}
protected override Rectangle GetContentBounds(Graphics graphics,
DataGridViewCellStyle cellStyle, int rowIndex)
{
var w = GetLabelWidth();
var r = base.GetContentBounds(graphics, cellStyle, rowIndex);
return new Rectangle(r.Left + w, r.Top, r.Width - w, r.Height);
}
protected override void OnContentClick(DataGridViewCellEventArgs e)
{
base.OnContentClick(e);
var g = this.DataGridView;
var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
var r1 = GetContentBounds(e.RowIndex);
var r2 = g.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
var p = new Point(r2.Left + r1.Left, r2.Top + r1.Bottom);
if (c.ContextMenuStrip != null)
c.ContextMenuStrip.Show(g, p);
}
private int GetLabelWidth()
{
var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
var text = c.LabelText;
return TextRenderer.MeasureText(text, c.DefaultCellStyle.Font).Width;
}
}
答案 1 :(得分:0)
我采用了这段代码并将其修改为更具动态性,这对我来说是一个很好的起点,对此我感到非常感谢。我希望能够使用按钮选择一个文件夹,然后单击链接打开该文件夹。
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Windows.Forms.VisualStyles;
using System.IO;
namespace Project
{
public class LinkButtonColumn : DataGridViewButtonColumn
{
private EventHandler<DataGridViewCellMouseEventArgs> buttonClickHandler;
private EventHandler<DataGridViewCellMouseEventArgs> linkClickHandler;
public LinkButtonColumn()
{
this.CellTemplate = new DataGridViewLinkButtonCell();
}
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
base.CellTemplate = value;
DataGridViewLinkButtonCell cell = CellTemplate as DataGridViewLinkButtonCell;
if (cell != null)
cell.ButtonClickHandler = ButtonClickHandler;
cell.LinkClickHandler = LinkClickHandler;
}
}
public EventHandler<DataGridViewCellMouseEventArgs> LinkClickHandler
{
get
{
return linkClickHandler;
}
set
{
DataGridViewLinkButtonCell cell = CellTemplate as DataGridViewLinkButtonCell;
if (cell != null)
{
if (value != null)
cell.LinkClickHandler += value;
else if (linkClickHandler != null)
cell.LinkClickHandler -= linkClickHandler;
}
linkClickHandler = value;
}
}
public EventHandler<DataGridViewCellMouseEventArgs> ButtonClickHandler
{
get
{
return buttonClickHandler;
}
set
{
DataGridViewLinkButtonCell cell = CellTemplate as DataGridViewLinkButtonCell;
if (cell != null)
{
if (value != null)
cell.ButtonClickHandler += value;
else if (buttonClickHandler != null)
cell.ButtonClickHandler -= buttonClickHandler;
}
buttonClickHandler = value;
}
}
}
internal sealed class DataGridViewLinkButtonColumn : DataGridViewColumn
{
private EventHandler<DataGridViewCellMouseEventArgs> buttonClickHandler;
private EventHandler<DataGridViewCellMouseEventArgs> linkClickHandler;
public string LabelText { get; set; }
public string ButtonText { get; set; }
public override object Clone()
{
var c = (DataGridViewLinkButtonColumn)base.Clone();
c.LabelText = this.LabelText;
c.ButtonText = this.ButtonText;
return c;
}
public DataGridViewLinkButtonColumn() : base(new DataGridViewLinkButtonCell())
{
}
public EventHandler<DataGridViewCellMouseEventArgs> LinkClickHandler
{
get
{
return linkClickHandler;
}
set
{
DataGridViewLinkButtonCell cell = CellTemplate as DataGridViewLinkButtonCell;
if (cell != null)
{
if (value != null)
cell.LinkClickHandler += value;
else if (linkClickHandler != null)
cell.LinkClickHandler -= linkClickHandler;
}
linkClickHandler = value;
}
}
public EventHandler<DataGridViewCellMouseEventArgs> ButtonClickHandler
{
get
{
return buttonClickHandler;
}
set
{
DataGridViewLinkButtonCell cell = CellTemplate as DataGridViewLinkButtonCell;
if (cell != null)
{
if (value != null)
cell.ButtonClickHandler += value;
else if (buttonClickHandler != null)
cell.ButtonClickHandler -= buttonClickHandler;
}
buttonClickHandler = value;
}
}
}
public class DataGridViewLinkButtonCell : DataGridViewButtonCell
{
private Rectangle clickRectangleValue = new Rectangle();
private string buttonPosion = "Middle";
public EventHandler<DataGridViewCellMouseEventArgs> ButtonClickHandler { get; set; }
public EventHandler<DataGridViewCellMouseEventArgs> LinkClickHandler { get; set; }
public Rectangle ClickRectangle
{
get
{
Rectangle newRect = new Rectangle();
switch (buttonPosion)
{
case "Bottom":
newRect = new Rectangle(clickRectangleValue.X + clickRectangleValue.Width - 20, clickRectangleValue.Y + (clickRectangleValue.Height - 20), 20, 20);
break;
case "Middle":
newRect = new Rectangle(clickRectangleValue.X + clickRectangleValue.Width - 20, clickRectangleValue.Y + ((clickRectangleValue.Height - 20) / 2), 20, 20);
break;
case "Top":
newRect = new Rectangle(clickRectangleValue.X + clickRectangleValue.Width - 20, clickRectangleValue.Y, 20, 20);
break;
}
return newRect;
}
}
public override object Clone()
{
DataGridViewLinkButtonCell cell = base.Clone() as DataGridViewLinkButtonCell;
if (cell != null)
{
cell.ButtonClickHandler = ButtonClickHandler;
cell.LinkClickHandler = LinkClickHandler;
}
return cell;
}
protected override void Paint(Graphics graphics, Rectangle clipBounds,
Rectangle cellBounds, int rowIndex,
DataGridViewElementStates elementState,
object value, object formattedValue, string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
var g = this.DataGridView;
var c = (DataGridViewLinkButtonColumn)this.OwningColumn;
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState,
value, formattedValue, errorText, cellStyle, advancedBorderStyle,
DataGridViewPaintParts.All &
~DataGridViewPaintParts.ContentBackground &
~DataGridViewPaintParts.ContentForeground);
var r1 = g.GetCellDisplayRectangle(c.Index, rowIndex, false);
Color forecolor = Color.Black;
TextFormatFlags horizontal = TextFormatFlags.HorizontalCenter;
TextFormatFlags vertical = TextFormatFlags.VerticalCenter;
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.BottomCenter:
horizontal = TextFormatFlags.HorizontalCenter;
vertical = TextFormatFlags.Bottom;
break;
case DataGridViewContentAlignment.BottomLeft:
horizontal = TextFormatFlags.Left;
vertical = TextFormatFlags.Bottom;
break;
case DataGridViewContentAlignment.BottomRight:
horizontal = TextFormatFlags.Right;
vertical = TextFormatFlags.Bottom;
break;
case DataGridViewContentAlignment.MiddleCenter:
horizontal = TextFormatFlags.HorizontalCenter;
vertical = TextFormatFlags.VerticalCenter;
break;
case DataGridViewContentAlignment.MiddleLeft:
horizontal = TextFormatFlags.Left;
vertical = TextFormatFlags.VerticalCenter;
break;
case DataGridViewContentAlignment.MiddleRight:
horizontal = TextFormatFlags.Right;
vertical = TextFormatFlags.VerticalCenter;
break;
case DataGridViewContentAlignment.TopCenter:
horizontal = TextFormatFlags.HorizontalCenter;
vertical = TextFormatFlags.Top;
break;
case DataGridViewContentAlignment.TopLeft:
horizontal = TextFormatFlags.Left;
vertical = TextFormatFlags.Top;
break;
case DataGridViewContentAlignment.TopRight:
horizontal = TextFormatFlags.Right;
vertical = TextFormatFlags.Top;
break;
}
if (g.Rows[rowIndex].Cells[c.Index].Selected)
{
if (value != null)
{
if (Directory.Exists(value.ToString()) || File.Exists(value.ToString()))
{
forecolor = Color.Red;
TextRenderer.DrawText(graphics, value.ToString(), new Font(cellStyle.Font, FontStyle.Underline),
r1, forecolor, Color.Empty,
horizontal |
vertical |
TextFormatFlags.TextBoxControl |
TextFormatFlags.WordBreak |
TextFormatFlags.EndEllipsis);
}
else
{
forecolor = Color.Blue;
TextRenderer.DrawText(graphics, value.ToString(), new Font(cellStyle.Font, FontStyle.Regular),
r1, Color.White, Color.Empty,
horizontal |
vertical |
TextFormatFlags.TextBoxControl |
TextFormatFlags.WordBreak |
TextFormatFlags.EndEllipsis);
}
}
}
else
{
if (value != null)
{
if (Directory.Exists(value.ToString()) || File.Exists(value.ToString()))
{
forecolor = Color.Blue;
TextRenderer.DrawText(graphics, value.ToString(), new Font(cellStyle.Font, FontStyle.Underline),
r1, forecolor, Color.Empty,
horizontal |
vertical |
TextFormatFlags.TextBoxControl |
TextFormatFlags.WordBreak |
TextFormatFlags.EndEllipsis);
}
else
{
forecolor = Color.Blue;
TextRenderer.DrawText(graphics, value.ToString(), new Font(cellStyle.Font, FontStyle.Regular),
r1, Color.Black, Color.Empty,
horizontal |
vertical |
TextFormatFlags.TextBoxControl |
TextFormatFlags.WordBreak |
TextFormatFlags.EndEllipsis);
}
}
}
Point cursorPosition = this.DataGridView.PointToClient(Cursor.Position);
if (cellBounds.Contains(cursorPosition))
{
clickRectangleValue = cellBounds;
Rectangle newRect = new Rectangle(cellBounds.X + 1,
cellBounds.Y + 1, cellBounds.Width - 4,
cellBounds.Height - 4);
DataGridViewCellStyle style = cellStyle;
style.Alignment = DataGridViewContentAlignment.MiddleCenter;
base.Paint(graphics, clipBounds, ClickRectangle, rowIndex, elementState,
value, c.ButtonText, errorText, style, advancedBorderStyle,
DataGridViewPaintParts.All);
}
}
protected override Rectangle GetContentBounds(Graphics graphics,
DataGridViewCellStyle cellStyle, int rowIndex)
{
var r = base.GetContentBounds(graphics, cellStyle, rowIndex);
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.BottomCenter:
buttonPosion = "Bottom";
break;
case DataGridViewContentAlignment.BottomLeft:
buttonPosion = "Bottom";
break;
case DataGridViewContentAlignment.BottomRight:
buttonPosion = "Bottom";
break;
case DataGridViewContentAlignment.MiddleCenter:
buttonPosion = "Middle";
break;
case DataGridViewContentAlignment.MiddleLeft:
buttonPosion = "Middle";
break;
case DataGridViewContentAlignment.MiddleRight:
buttonPosion = "Middle";
break;
case DataGridViewContentAlignment.TopCenter:
buttonPosion = "Top";
break;
case DataGridViewContentAlignment.TopLeft:
buttonPosion = "Top";
break;
case DataGridViewContentAlignment.TopRight:
buttonPosion = "Top";
break;
}
clickRectangleValue = r;
return new Rectangle(ClickRectangle.X, ClickRectangle.Y, ClickRectangle.Width, ClickRectangle.Height);
}
protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
{
int x = e.X;
int y = e.Y;
Point cursorPosition = this.DataGridView.PointToClient(Cursor.Position);
var g = this.DataGridView;
var r1 = GetContentBounds(e.RowIndex);
var r2 = g.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
r1.X = r1.X + r2.X;
r1.Y = r1.Y + r2.Y;
if (r1.Contains(cursorPosition))
{
if (ButtonClickHandler != null)
{
this.ButtonClickHandler.Invoke(this,e);
}
}
else
{
if (r2.Contains(cursorPosition))
{
if (LinkClickHandler != null)
{
this.LinkClickHandler.Invoke(this, e);
}
}
}
}
protected override void OnMouseEnter(int rowIndex)
{
Cursor.Current = Cursors.Hand;
this.DataGridView.Cursor = Cursor.Current;
this.DataGridView.InvalidateCell(this);
}
protected override void OnMouseLeave(int rowIndex)
{
this.DataGridView.InvalidateCell(this);
Cursor.Current = Cursors.Default;
this.DataGridView.Cursor = Cursor.Current;
}
}
}
然后我实用地将列添加到网格中。
if (!Addendum_dataGridView.Columns.Contains("Folder_Location"))
{
DataGridViewLinkButtonColumn textButtonColumn = new DataGridViewLinkButtonColumn();
textButtonColumn.ValueType = typeof(string);
textButtonColumn.HeaderText = "Folder Location";
textButtonColumn.ButtonText = "...";
textButtonColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
textButtonColumn.DefaultCellStyle.Padding = new Padding(1, 0, 0, 0);
textButtonColumn.Width = 100;
textButtonColumn.Name = "Folder_Location";
textButtonColumn.DataPropertyName = "Folder_Location";
textButtonColumn.LinkClickHandler = (o, e) =>
{
if(Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value != DBNull.Value)
{
if (Directory.Exists(Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value.ToString()) || File.Exists(Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value.ToString()))
{
Process.Start(Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value.ToString());
}
}
};
textButtonColumn.ButtonClickHandler = (o, e) =>
{
CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.Multiselect = false;
cofd.Title = "Select Addendum Folder";
if (Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value != DBNull.Value)
{
cofd.InitialDirectory = Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Value.ToString();
}
else
{
cofd.InitialDirectory = Directory.GetParent(Directory.GetParent(SQL_Commands.Get_Data("select top 1 Quote_Location from [Index].[Estimates_Project_info] where Project_ID = " + P_ID).FirstOrDefault()).ToString()).ToString();
}
if (cofd.ShowDialog() == CommonFileDialogResult.Ok)
{
if (Addendum_dataGridView.Rows[e.RowIndex].IsNewRow)
{
int r = Addendum_dataGridView.NewRowIndex;
DataTable dt = Addendum_dataGridView.DataSource as DataTable;
DataRow row = dt.NewRow();
row["Addendum_Number"] = Path.GetFileNameWithoutExtension(cofd.FileName.ToString());
row["Folder_Location"] = cofd.FileName.ToString();
dt.Rows.Add(row);
dt = Addendum_dataGridView.DataSource as DataTable;
bool blank = true;
DataGridViewRow dgvr = Addendum_dataGridView.Rows[Addendum_dataGridView.Rows.Count - 2];
for (int i = 0; i < Addendum_dataGridView.ColumnCount;i++)
{
if (dgvr.Cells[i].Value != DBNull.Value)
{
blank = false;
}
}
if (blank)
{
Addendum_dataGridView.Rows.RemoveAt(Addendum_dataGridView.Rows.Count - 2);
}
insert_Addendum = true;
Addendum_Data_Update(r);
}
else
{
Addendum_dataGridView["Folder_Location",e.RowIndex].Value = cofd.FileName.ToString();Addendum_dataGridView.Rows[e.RowIndex].Cells[Addendum_dataGridView.Columns["Folder_Location"].Index].Selected = true;
Addendum_Data_Update(e.RowIndex);
}
}
};
Addendum_dataGridView.Columns.Insert(Addendum_dataGridView.Columns.Count,textButtonColumn);
}