技术总结:c# 之winform datagridview自定义操作列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术总结:c# 之winform datagridview自定义操作列相关的知识,希望对你有一定的参考价值。


datagridview在winform的框架里面就和html里面的table一样。

但不同的是,原生的datagridview里面并没有操作列这个概念,默认的列类型 有下拉框、文本、按钮、图片、链接这几类,如果需要其他的样式还需要重新写。

其实大部分需求都是如图的效果,当然你使用了别的组件【不是官方自带】,可能实现如图的效果很简单

技术总结:c#

下面讲讲如图==》操作列 有多个按钮的不同实现方式

1.1 方式一

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace chao.net

public partial class FormTest2 : Form

public FormTest2()

InitializeComponent();


private void toolStripLabel1_Click(object sender, EventArgs e)




private void FormTest2_Load(object sender, EventArgs e)

this.dataGridView1.AutoGenerateColumns = false;;
this.dataGridView1.CellMouseClick += dataGridView1_CellMouseClick;
this.dataGridView1.CellPainting += dataGridView1_CellPainting;
this.dataGridView1.Rows.Add();






/// <summary>
/// 单元格重绘
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

if (e.ColumnIndex >= 0 && e.RowIndex >= 0)

if (this.dataGridView1.Columns[e.ColumnIndex].HeaderText == "操作")

StringFormat sf = StringFormat.GenericDefault.Clone() as StringFormat;//设置重绘入单元格的字体样式
sf.FormatFlags = StringFormatFlags.DisplayFormatControl;
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.Trimming = StringTrimming.EllipsisCharacter;

//e.PaintContent

e.PaintBackground(e.CellBounds, false);//重绘边框

//设置要写入字体的大小
System.Drawing.Font myFont = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
//myFon

SizeF sizeDel = e.Graphics.MeasureString("删除", myFont);

SizeF sizeMod = e.Graphics.MeasureString("修改", myFont);
SizeF sizeLook = e.Graphics.MeasureString("查看", myFont);

float fDel = sizeDel.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width); //
float fMod = sizeMod.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width);
float fLook = sizeLook.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width);

//设置每个“按钮的边界”
RectangleF rectDel = new RectangleF(e.CellBounds.Left, e.CellBounds.Top, e.CellBounds.Width * fDel, e.CellBounds.Height);

RectangleF rectMod = new RectangleF(rectDel.Right, e.CellBounds.Top, e.CellBounds.Width * fMod, e.CellBounds.Height);

RectangleF rectLook = new RectangleF(rectMod.Right, e.CellBounds.Top, e.CellBounds.Width * fLook, e.CellBounds.Height);

e.Graphics.DrawString("删除", myFont, Brushes.Black, rectDel, sf); //绘制“按钮”
e.Graphics.DrawString("修改", myFont, Brushes.Black, rectMod, sf);
e.Graphics.DrawString("查看", myFont, Brushes.Black, rectLook, sf);

e.Handled = true;






/// <summary>
/// 鼠标点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)

if (e.ColumnIndex >= 0 && e.RowIndex >= 0)

Point curPosition = e.Location;//当前鼠标在当前单元格中的坐标
if (this.dataGridView1.Columns[e.ColumnIndex].HeaderText == "操作")

//this.dataGridView1.Columns[e.ColumnIndex].Add

Graphics g = this.dataGridView1.CreateGraphics();
System.Drawing.Font myFont = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
SizeF sizeDel = g.MeasureString("删除", myFont);
SizeF sizeMod = g.MeasureString("修改", myFont);
SizeF sizeLook = g.MeasureString("查看", myFont);
float fDel = sizeDel.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width);
float fMod = sizeMod.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width);
float fLook = sizeLook.Width / (sizeDel.Width + sizeMod.Width + sizeLook.Width);

Rectangle rectTotal = new Rectangle(0, 0, this.dataGridView1.Columns[e.ColumnIndex].Width, this.dataGridView1.Rows[e.RowIndex].Height);
RectangleF rectDel = new RectangleF(rectTotal.Left, rectTotal.Top, rectTotal.Width * fDel, rectTotal.Height);
RectangleF rectMod = new RectangleF(rectDel.Right, rectTotal.Top, rectTotal.Width * fMod, rectTotal.Height);
RectangleF rectLook = new RectangleF(rectMod.Right, rectTotal.Top, rectTotal.Width * fLook, rectTotal.Height);
//判断当前鼠标在哪个“按钮”范围内
if (rectDel.Contains(curPosition))//删除
MessageBox.Show("点击删除按钮");
else if (rectMod.Contains(curPosition))//修改
MessageBox.Show("点击修改按钮");
else if (rectLook.Contains(curPosition))//查看
MessageBox.Show("点击查看按钮");





private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)




主要方法是:dataGridView1_CellPainting  就是重新绘制单元格。代码在FormTest2.cs里面,进入链接在最下面。

效果:

技术总结:c#

技术总结:c#

1.2 方式二

    使用右键菜单==》也可套用点击行里面的按钮显示菜单。【学会举一反三就行】

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace chao.net

public partial class FormTest3 : Form

public FormTest3()

InitializeComponent();


private void FormTest3_Load(object sender, EventArgs e)

this.dataGridView1.AutoGenerateColumns = false; ;
this.dataGridView1.MouseClick += dataGridView1_MouseClick;
this.dataGridView1.Rows.Add();




/// <summary>
/// stripItem0点击事件-删除选中行
/// </summary>
private void stripItems0_Click(object sender, EventArgs e)

MessageBox.Show("-删除选中行--");


private void dataGridView1_MouseClick(object sender, MouseEventArgs e)

ContextMenuStrip strip = new ContextMenuStrip();
strip.ShowImageMargin = false;//设置右击菜单属性
strip.Items.Add("删除选定行");
strip.Items.Add("添加行");

strip.Items[0].Click += stripItems0_Click;//弹出菜单第一项点击事件
strip.Items[1].Click += stripItems1_Click;//弹出菜单第二项点击事件

if (e.Button == MouseButtons.Right)//右键点击

strip.Show(this.dataGridView1, e.Location);//弹出菜单



/// <summary>
/// 弹出菜单第二项点击事件
/// </summary>
private void stripItems1_Click(object sender, EventArgs e)

MessageBox.Show("-添加行-");



解释:主要方法是:dataGridView1_MouseClick,这边判断是否右键点击【操作请在datagridview里面右键点击】。代码在FormTest3.cs里面,进入链接在最下面。【其实这种思维更适合客户端,网页和桌面应用还是有区别的】

效果:

技术总结:c#

技术总结:c#

1.3 方式三

    是我参考网上一些固有样式,写出的一个动态的操作列,可以适合权限管理【按钮】。推荐使用。当然可能有些小问题,暂时我还没发现。这种样式和后端管理的操作列类似。如果按钮超出列的宽度,请设置合适的该列的宽度。

using chao.net.UIL;
using chao.net.UIL.UserControls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace chao.net

public partial class FormTest : Form





public FormTest()

InitializeComponent();


private void FormTest_Load(object sender, EventArgs e)


this.dataGridView1.AutoGenerateColumns = false;


DataGridViewActionButtonColumn dataGridViewColumn = new DataGridViewActionButtonColumn();
dataGridViewColumn.Width = 240;
dataGridViewColumn.HeaderText = "操作列2";
dataGridViewColumn.Resizable = DataGridViewTriState.False;
this.dataGridView1.Columns.Add(dataGridViewColumn);

/*
DataGridViewDetailButtonColumn buttonColumn = new DataGridViewDetailButtonColumn();
buttonColumn.HeaderText = "操作列3";
this.dataGridView1.Columns.Add(buttonColumn);*/

this.dataGridView1.Rows.Add();
/* this.dataGridView1.RowHeadersVisible = true;
this.dataGridView1.ColumnHeadersVisible = true;*/







private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)


if (this.dataGridView1.Columns[e.ColumnIndex].HeaderText == "操作列2")

DataGridViewActionButtonColumn dataGridViewColumn = (DataGridViewActionButtonColumn)this.dataGridView1.Columns[e.ColumnIndex];

//DataGridViewActionButtonCell dataGridViewActionButtonCell = (DataGridViewActionButtonCell)dataGridViewColumn.CellTemplate;

List<ActionButton> buttonList = dataGridViewColumn.ButtonList;

foreach(ActionButton act in buttonList)
if (act.MouseOnButton)//此时鼠标悬浮在上面

Console.WriteLine("点击了:" + act.Name);
//MessageBox.Show("点击了:"+act.Name);









解释:主要方法是:FormTest_Load 和 dataGridView1_MouseClick,FormTest_Load 主要是自定义单元格,dataGridView1_MouseClick是点击判断点击的按钮区域进而做业务处,需要使用自定义的列DataGridViewActionButtonColumn和自定义的单元格DataGridViewActionButtonCell。代码在FormTest.cs里面,进入链接在最下面。【其实这种思维更适合客户端,网页和桌面应用还是有区别的】

效果:

技术总结:c#

技术总结:c#

技术总结:c#

源代码:​​csharp-demo-code: c#实例代码 - Gitee.com​

[暂时不对外开放,等过段时间]


以上是关于技术总结:c# 之winform datagridview自定义操作列的主要内容,如果未能解决你的问题,请参考以下文章

C# .net不同版本中winform控件 dataGrid /DataGrid/DataGridView 有啥区别

C# datagrid 隐藏列(编号)

WinForm杂记:C#之DataTable类(总结)

关于c# winform datagrid的列宽如何设置为自动适应内容宽度? 在网上找到的这段代码

C# Winform程序中使用DataGridView时单元格无法显示全部内容时,如何右对齐,省略号在左边。

C# winform程序中如何向datagridview中添加一行