外贸网站建设公司方案seo的优化方案
实现原因
因为现有的DataGridView控件无法支持在单元格DataGridViewCell上显示多个甚至是多种类型的控件
实现效果
效果1
效果2
实现代码
核心代码实现
using System;
using System.Drawing;
using System.Windows.Forms;namespace DataGridViewCellExtLib
{/// <summary>/// DataGridViewCell扩展类/// </summary>public static class DataGridViewCellExtension{/// <summary>/// 添加Panel控件到DataGridView/// </summary>/// <param name="cell">DataGridViewCell对象</param>/// <param name="dataGridView">DataGridView对象</param>/// <returns>返回已指定好大小,位置,添加到DataGridView控件的Panel对象</returns>/// <exception cref="ArgumentNullException">/// 如果cell为Null,抛出ArgumentNullException异常/// 如果dataGridView为Null,抛出ArgumentNullException异常/// </exception>public static Panel AddPanelControl(this DataGridViewCell cell, DataGridView dataGridView){if (cell == null){throw new ArgumentNullException(nameof(cell));}if (dataGridView == null){throw new ArgumentNullException(nameof(dataGridView));}var panel = new Panel{//默认Panel颜色为透明BackColor = Color.Transparent};//添加控件到DataGridViewdataGridView.Controls.Add(panel);//获取单元格的矩形范围Rectangle rectangle = dataGridView.GetCellDisplayRectangle(cell.ColumnIndex, cell.RowIndex, false);//设置Panel的大小panel.Size = new Size(){Width = rectangle.Width,Height = rectangle.Height};//显示Panelpanel.Visible = true;//设置Panel位置panel.Location = new Point(rectangle.Left, rectangle.Top);//将Panel和DataGridViewCell绑定在一起panel.Tag = new TagPlus<DataGridViewCell>{Binding = cell};cell.Tag = new TagPlus<Panel>{Binding = panel};return panel;}/// <summary>/// 从DataGridView中移除Panel控件/// </summary>/// <param name="cell">DataGridViewCell对象</param>/// <param name="dataGridView">DataGridView对象</param>/// <exception cref="ArgumentNullException">/// 如果cell为Null,抛出ArgumentNullException异常/// 如果dataGridView为Null,抛出ArgumentNullException异常/// </exception>public static void RemovePanelControl(this DataGridViewCell cell, DataGridView dataGridView){if (cell == null){throw new ArgumentNullException(nameof(cell));}if (dataGridView == null){throw new ArgumentNullException(nameof(dataGridView));}var panel = ((TagPlus<Panel>)cell.Tag).Binding;//移除Panel控件dataGridView.Controls.Remove(panel);panel.Dispose();}/// <summary>/// 重新在DataGridView控件中设置Panel位置/// </summary>/// <param name="cell">DataGridViewCell对象</param>/// <param name="dataGridView">DataGridView对象</param>/// <exception cref="ArgumentNullException">/// 如果cell为Null,抛出ArgumentNullException异常/// 如果dataGridView为Null,抛出ArgumentNullException异常/// </exception>public static void ResetPanelControlLocation(this DataGridViewCell cell, DataGridView dataGridView){if (cell == null){throw new ArgumentNullException(nameof(cell));}if (dataGridView == null){throw new ArgumentNullException(nameof(dataGridView));}var tagPlus = (TagPlus<Panel>)cell.Tag;var panel = tagPlus.Binding;//获取单元格的矩形范围Rectangle rectangle = dataGridView.GetCellDisplayRectangle(cell.ColumnIndex, cell.RowIndex, false);//设置Panel位置panel.Location = new Point(rectangle.Left, rectangle.Top);}}/// <summary>/// Tag扩展类/// </summary>/// <typeparam name="T">需要绑定的数据类型</typeparam>public class TagPlus<T>{/// <summary>/// 需要绑定的元素/// </summary>public T Binding { get; set; }/// <summary>/// 将Control.Tag属性保留到当前属性上/// </summary>public object Tag { get; set; }}
}
程序代码地址下载
https://gitee.com/GandalfGao/cell-with-control.git
设计思路
1. 为什么以DataGridViewCell的扩展类方式实现
从界面的实现角度来看,控件是添加到单元格中的(实际却不是这样的,添加显示的控件实际和DataGridViewCell一点关系都没有,它们也没有父级和子级的关系,添加的控件只和DataGridView控件有父级和子级的关系)。因此,我想设计一个这样的扩展方法,使其开发起来就好像是直接对DataGridViewCell操作一样, 比如添加控件,虽然实际是往DataGridView控件上做添加,但是开发者在用扩展方法时,就仿佛是在对DataGridViewCell做添加一样,这样的话在感官上显得更加直接
2. 为什么添加到DataGridView的都是只是一个Panel控件
a. 是为了化繁为简
我需要设计一个root的控件,用这个控件来承接多个甚至是多个不同种类的子控件。这样的设计的好处有两点:
第一:对于DataGridViewCell来说,只需要面对这一个root控件即可,它不需要再关注root控件里面究竟设计了什么样的控件,它们的位置是在哪里。它只需要对一个控件做好负责,那就是这个root控件,只要设计好这个root的控件大小和其位置就可以了,大小是单元格的大小,位置是单元格的位置
第二:设计这个root控件之后,子控件的位置就是相对root控件位置来设置了,不需要再相对DataGridView控件位置来设置。
b. 为什么选择Panel做为这个root控件
因为子控件在Panel控件中布局更加简单和自由
3. TagPlus类是做什么用的
简单来说,Control类中带有Tag属性,TagPlus可以理解为是Tag属性的扩展版
那为什么需要这个类来做为Tag的扩展呢?
这就得提到我其中的一个设计思路。由于DatGridViewCell控件和Panel控件之间没有关联关系,而是DataGridView控件和Panel有关联关系,且是一对多的关系。所以我就想通过某种方式将DataGridViewCell控件和Panel控件绑定在一起,让它们之间有一定关联关系,且是一对一的关联关系,首先想到的就是用Control的Tag属性,但是担心Tag属性被占用后,如果想要添加别的数据到Tag上那就无法赋值了,所以我加了TagPlus类,在提供绑定控件属性的同时,且也保留了Tag属性。绑定之后呢,DataGridViewCell和Panel就有了关联关系,DataGridViewCell就成了Panel逻辑上的“父控件”,Panel成了DataGridViewCell逻辑上的“子控件”,这样也更好的可以通过DataGridViewCell去访问到Panel控件,通过Panel控件更好的访问到DataGridViewCell控件。
结尾
如果您觉得我还写的不错,请给我一点点的鼓励,您的鼓励就是我坚持的动力,当然啦,一切要量力而行,不要勉强哦!