C# 行.Add和行.AddRange与自定义DataGridViewRow之间的.Net DataGridView差异
C# 行.Add和行.AddRange与自定义DataGridViewRow之间的.Net DataGridView差异,c#,datagridview,datagridviewrow,C#,Datagridview,Datagridviewrow,DataGridViewControl的奇怪行为今天花了我不少时间 TL;DR:Rows.Add(MyOwnFancyRow)将MyOwnFancyRow的克隆添加到DGV,而Rows.AddRange(new MWERow[]{MyOwnFancyRow})添加MyOwnFancyRow本身。在写了所有这些之后,我明白了,但仍然不明白为什么 假设:DataGridView.Rows.Add()和DataGridView.Rows.AddRange()根据行模板处理新行的插入 实验:我使用unb
DataGridViewControl
的奇怪行为今天花了我不少时间
TL;DR:Rows.Add(MyOwnFancyRow)
将MyOwnFancyRow
的克隆添加到DGV,而Rows.AddRange(new MWERow[]{MyOwnFancyRow})
添加MyOwnFancyRow
本身。在写了所有这些之后,我明白了,但仍然不明白为什么
假设:DataGridView.Rows.Add()
和DataGridView.Rows.AddRange()
根据行模板处理新行的插入
实验:我使用unboundDataGridView
s,设计用于显示复杂类,并为用户提供根据自己的喜好配置此类实例的方法。我可以从XML加载一些实例并显示它们,同时也可以给用户添加新实例的机会(想想dgv.allowUserToAddress=true;
)
为了正确显示这些实例,我创建了自定义的DataGridViewRow
s来处理用户和实例之间的所有交互。这样,我就可以将我的实例插入另一个完全不同形式的DataGridView
,而无需复制所有处理代码。这一排为我做了这一切
请为我的最小(非)工作示例考虑这不是过于复杂的类:
class MWEObject : ICloneable {
public string Value1 { get; internal set; }
public double Value2 { get; internal set; }
public delegate void OnMWEObjectChanged();
public event OnMWEObjectChanged ObjectChanged;
public MWEObject() {
Value1 = "Default"; Value2 = 0;
}
public MWEObject(string in_Value1, double in_Value2) {
Value1 = in_Value1; Value2 = in_Value2;
}
public void UpdateObject(MWEObject in_Object) {
Value1 = in_Object.Value1;
Value2 = in_Object.Value2;
if (ObjectChanged != null)
ObjectChanged.Invoke();
}
public override string ToString() {
return "Value1: " + Value1 + " Value2: " + Value2.ToString("0.000");
}
public object Clone() {
return new MWEObject(Value1, Value2);
}
}
这个类本身无法轻松地进入DataGridView
,因此这里有一个自定义的DataGridView行
来处理显示和更新(我试图使它尽可能完整但尽可能简短,这样概念就变得清晰,我可以指出错误):
这一行背后的概念如下:
- 静态方法允许我设置所需的任何
DataGridView
DataGridView
将指定特定的事件处理程序来处理添加行和编辑单元格=>这样可以保持表单的代码干净,并且可以在添加行后显示正确的值
- 列被添加到
DataGridView
CellTemplate
设置为最基本的行=>其中使用默认值实例化对象(在“添加新行”行中显示值,默认值总是很好)
- 请注意克隆方法(根据文档,该方法必须存在)。我们将在短时间内移动评论
行本身首先创建所需的单元格(CreateCells(templateDGV);
),这就是我必须提供指向该行将要添加到的DataGridView的链接的原因=>我需要列名
要完成所有工作,我们需要一个名为dgv的表单,其中包含1个DataGridView
和6个按钮
s,因此它是:
public partial class frm_Test : Form {
List<MWEObject> theObjects;
List<MWEObject> theSecondObjects;
public frm_Test() {
InitializeComponent();
theObjects = new List<MWEObject>()
{
new MWEObject("test 1", 1),
new MWEObject("test 2", 2),
new MWEObject("test 3", 3),
new MWEObject("test 4", 4)
};
theSecondObjects = new List<MWEObject>();
}
private void btn_SetupDGV_Click(object sender, EventArgs e) {
MWERow.SetupDGV(dgv);
dgv.RowsAdded += Dgv_RowsAdded;
}
private void Dgv_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) {
DataGridView dgv = sender as DataGridView;
if (dgv != null)
{
int StartIndex = e.RowIndex;
if ((dgv.AllowUserToAddRows && StartIndex != 0) && StartIndex == dgv.Rows.Count - 1)
StartIndex--;
foreach (int i in Enumerable.Range(StartIndex, e.RowCount))
theSecondObjects.Add(((MWERow)dgv.Rows[i]).theObject);
}
}
private void btn_ShowLists_Click(object sender, EventArgs e) {
MessageBox.Show("Rows: " + Environment.NewLine + string.Join(Environment.NewLine, dgv.Rows.Cast<MWERow>().Select(x => x.theObject.ToString() + (x.IsNewRow ? " isNew" : ""))));
MessageBox.Show("List: " + Environment.NewLine + string.Join(Environment.NewLine, theObjects.Select(x => x.ToString())));
MessageBox.Show("Second List: " + Environment.NewLine + string.Join(Environment.NewLine, theSecondObjects.Select(x => x.ToString())));
}
private void btn_AddSingleItem_Click(object sender, EventArgs e) {
dgv.Rows.Add(new MWERow(new MWEObject("1 Test", 1), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("2 Test", 2), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("3 Test", 3), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("4 Test", 4), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("5 Test", 5), dgv));
}
private void btn_AddBulkItems_Click(object sender, EventArgs e) {
dgv.Rows.AddRange(new MWERow[]
{
new MWERow(new MWEObject("1 Test", 1), dgv),
new MWERow(new MWEObject("2 Test", 2), dgv),
new MWERow(new MWEObject("3 Test", 3), dgv),
new MWERow(new MWEObject("4 Test", 4), dgv),
new MWERow(new MWEObject("5 Test", 5), dgv)
});
}
private void btn_AddSingleList_Click(object sender, EventArgs e) {
foreach (MWEObject o in theObjects)
dgv.Rows.Add(new MWERow(o, dgv));
}
private void btn_AddBulkList_Click(object sender, EventArgs e) {
dgv.Rows.AddRange(theObjects.Select(x => new MWERow(x, dgv)).ToArray());
}
}
公共部分类frm_测试:表格{
列出目标;
列出这些共有对象;
公共frm_测试(){
初始化组件();
对象=新列表()
{
新MWEObject(“测试1”,1),
新MWEObject(“测试2”,2),
新MWEObject(“测试3”,3),
新MWEObject(“测试4”,4)
};
theSecondObjects=新列表();
}
私有无效btn_设置DGV_单击(对象发送者,事件参数e){
MWERow.设置dgv(dgv);
dgv.RowsAdded+=dgv_RowsAdded;
}
私有void Dgv_RowsAdded(对象发送方,DataGridViewRowsAddedEventArgs e){
DataGridView dgv=作为DataGridView的发送方;
如果(dgv!=null)
{
int StartIndex=e.RowIndex;
if((dgv.allowUserToAddress&&StartIndex!=0)&&StartIndex==dgv.Rows.Count-1)
StartIndex--;
foreach(可枚举范围中的int i(StartIndex,e.RowCount))
这些condobjects.Add(((MWERow)dgv.Rows[i])。对象);
}
}
私有无效btn\u显示列表\u单击(对象发送者,事件参数e){
MessageBox.Show(“行:”+Environment.NewLine+string.Join(Environment.NewLine,dgv.Rows.Cast()。选择(x=>x.theObject.ToString()+(x.IsNewRow?“isNew”)));
Show(“列表:+Environment.NewLine+string.Join(Environment.NewLine,theObjects.Select(x=>x.ToString())));
Show(“第二个列表:”+Environment.NewLine+string.Join(Environment.NewLine,theSecondObjects.Select(x=>x.ToString()));
}
私有void btn\u AddSingleItem\u单击(对象发送者,事件参数e){
dgv.Rows.Add(新MWERow(新MWEObject(“1测试”,1),dgv));
dgv.Rows.Add(新MWERow(新MWEObject(“2测试”,2),dgv));
dgv.Rows.Add(新MWERow(新MWEObject(“3测试”,3),dgv));
dgv.Rows.Add(新MWERow(新MWEObject(“4测试”,4),dgv));
dgv.Rows.Add(新MWERow(新MWEObject(“5测试”,5),dgv));
}
私有void btn\u AddBulkItems\u单击(对象发送者,事件参数e){
dgv.Rows.AddRange(新MWERow[]
{
新MWERow(新MWEObject(“1测试”,1),dgv),
新MWERow(新MWEObject(“2测试”,2),dgv),
新MWERow(新MWEObject(“3测试”,3),dgv),
新MWERow(新MWEObject(“4测试”,4),dgv),
新MWERow(新MWEObject(“5测试”,5),dgv)
});
}
私有void btn\u AddSingleList\u单击(对象发送者,事件参数e){
foreach(对象中的MWEObject o)
添加(新的MWERow(o,dgv));
}
私有无效btn\u添加批量列表\u单击(对象发送者,事件参数e){
dgv.Rows.AddRange(theObjects.Select(x=>newmwerow(x,dgv)).ToArray();
}
}
按钮功能的简短说明:
- 一个按钮设置DataGridView
- 一个按钮显示:所有行中的“对象”、“对象”列表的内容(固定)和“对象”列表的内容(随着每次添加而增加)
- 一个按钮添加新行insta
public partial class frm_Test : Form {
List<MWEObject> theObjects;
List<MWEObject> theSecondObjects;
public frm_Test() {
InitializeComponent();
theObjects = new List<MWEObject>()
{
new MWEObject("test 1", 1),
new MWEObject("test 2", 2),
new MWEObject("test 3", 3),
new MWEObject("test 4", 4)
};
theSecondObjects = new List<MWEObject>();
}
private void btn_SetupDGV_Click(object sender, EventArgs e) {
MWERow.SetupDGV(dgv);
dgv.RowsAdded += Dgv_RowsAdded;
}
private void Dgv_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) {
DataGridView dgv = sender as DataGridView;
if (dgv != null)
{
int StartIndex = e.RowIndex;
if ((dgv.AllowUserToAddRows && StartIndex != 0) && StartIndex == dgv.Rows.Count - 1)
StartIndex--;
foreach (int i in Enumerable.Range(StartIndex, e.RowCount))
theSecondObjects.Add(((MWERow)dgv.Rows[i]).theObject);
}
}
private void btn_ShowLists_Click(object sender, EventArgs e) {
MessageBox.Show("Rows: " + Environment.NewLine + string.Join(Environment.NewLine, dgv.Rows.Cast<MWERow>().Select(x => x.theObject.ToString() + (x.IsNewRow ? " isNew" : ""))));
MessageBox.Show("List: " + Environment.NewLine + string.Join(Environment.NewLine, theObjects.Select(x => x.ToString())));
MessageBox.Show("Second List: " + Environment.NewLine + string.Join(Environment.NewLine, theSecondObjects.Select(x => x.ToString())));
}
private void btn_AddSingleItem_Click(object sender, EventArgs e) {
dgv.Rows.Add(new MWERow(new MWEObject("1 Test", 1), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("2 Test", 2), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("3 Test", 3), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("4 Test", 4), dgv));
dgv.Rows.Add(new MWERow(new MWEObject("5 Test", 5), dgv));
}
private void btn_AddBulkItems_Click(object sender, EventArgs e) {
dgv.Rows.AddRange(new MWERow[]
{
new MWERow(new MWEObject("1 Test", 1), dgv),
new MWERow(new MWEObject("2 Test", 2), dgv),
new MWERow(new MWEObject("3 Test", 3), dgv),
new MWERow(new MWEObject("4 Test", 4), dgv),
new MWERow(new MWEObject("5 Test", 5), dgv)
});
}
private void btn_AddSingleList_Click(object sender, EventArgs e) {
foreach (MWEObject o in theObjects)
dgv.Rows.Add(new MWERow(o, dgv));
}
private void btn_AddBulkList_Click(object sender, EventArgs e) {
dgv.Rows.AddRange(theObjects.Select(x => new MWERow(x, dgv)).ToArray());
}
}