最近在用dataGridView.DataSource,由于dataGridView.DataSource会绑定不同类型的数据,需要一个通用的删除、添加功能
添加了弹出菜单ContextMenuStrip后需要针对不同的类型数据添加“插入一行”、“删除选中行”等功能。
代码不多,写成了 ContextMenuStrip 的扩展
var obj = dataGridView.DataSource
var type = obj.GetType();
var properties = type?.GetProperties();
var itemProperties = properties
?.FirstOrDefault(p => p.Name == "Item");
var d = itemProperties.DeclaringType;//获取声明类型,也就是 BindList<T>
var methods = d.GetMethods();//再获取公共方法,调用 Add、RemoveAt等
foreach (var mth in methods)
{
if (mth.Name == "RemoveAt")
{
foreach (int index in removeIndexs.OrderByDescending(i => i))
mth.Invoke(obj, new object[] { index });
}
}
/// <summary>
/// BindList 公共方法
/// get_Count
/// get_Item
/// set_Item
/// Add
/// Clear
/// CopyTo
/// Contains
/// GetEnumerator
/// IndexOf
/// Insert
/// Remove
/// RemoveAt
/// Equals
/// GetHashCode
/// GetType
/// ToString
/// </summary>
public static class ContextMenuStripExten
{
public static void AddItem_RemoveSelect(this ContextMenuStrip menu, Control removeCtl, string text = "删除全部选中行")
{
if (removeCtl is DataGridView || removeCtl is ListBox || removeCtl is CheckedListBox)
{
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
object obj = null;
List<int> removeIndexs = new List<int>();
if (removeCtl is DataGridView)
{
var dv = (DataGridView)removeCtl;
if (dv.SelectedRows?.Count == 0) return;
foreach (DataGridViewRow row in dv.SelectedRows)
removeIndexs.Add(row.Index);
obj = dv.DataSource;
}
else if (removeCtl is ListBox)
{
var box = (ListBox)removeCtl;
if (box.SelectedIndices?.Count == 0) return;
foreach (int index in box.SelectedIndices)
removeIndexs.Add(index);
obj = box.DataSource;
}
else if (removeCtl is CheckedListBox)
{
var box = (CheckedListBox)removeCtl;
if (box.SelectedIndices?.Count == 0) return;
foreach (int index in box.SelectedIndices)
removeIndexs.Add(index);
obj = box.DataSource;
}
var type = obj.GetType();
var properties = type?.GetProperties();
var itemProperties = properties
?.FirstOrDefault(p => p.Name == "Item");
var d = itemProperties.DeclaringType;
var methods = d.GetMethods();
foreach (var mth in methods)
{
if (mth.Name == "RemoveAt")
{
foreach (int index in removeIndexs.OrderByDescending(i => i))
mth.Invoke(obj, new object[] { index });
}
}
};
}
else if (removeCtl is TreeView)
{
var tv = (TreeView)removeCtl;
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
if (tv.SelectedNode == null)
return;
if (tv.SelectedNode.Level > 0)
tv.SelectedNode.Parent.Nodes.Remove(tv.SelectedNode);
else
tv.Nodes.Remove(tv.SelectedNode);
};
}
}
public static void AddItem_InsertBeforSelect(this ContextMenuStrip menu, Control removeCtl, string text = "插入一行")
{
if (removeCtl is DataGridView || removeCtl is ListBox || removeCtl is CheckedListBox)
{
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
object obj = null;
int selectedIndexs = 0;
if (removeCtl is DataGridView)
{
var dv = (DataGridView)removeCtl;
if (dv.SelectedRows?.Count == 0) return;
selectedIndexs = dv.SelectedRows[0].Index;
obj = dv.DataSource;
}
else if (removeCtl is ListBox)
{
var box = (ListBox)removeCtl;
if (box.SelectedIndices?.Count == 0) return;
selectedIndexs = box.SelectedIndex;
obj = box.DataSource;
}
else if (removeCtl is CheckedListBox)
{
var box = (CheckedListBox)removeCtl;
if (box.SelectedIndices?.Count == 0) return;
selectedIndexs = box.SelectedIndex;
obj = box.DataSource;
}
var type = obj.GetType();
var properties = type?.GetProperties();
var itemProperties = properties
?.FirstOrDefault(p => p.Name == "Item");
var d = itemProperties.DeclaringType;
var methods = d.GetMethods();
foreach (var mth in methods)
{
if (mth.Name == "Insert")
{
try
{
Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
dynamic instance = assembly.CreateInstance(itemProperties.PropertyType.FullName); // 创建类的实例,返回为 object 类型,需要强制类型转换
mth.Invoke(obj, new object[] { selectedIndexs, instance });
}
catch { }
}
}
};
}
else if (removeCtl is TreeView)
{
var tv = (TreeView)removeCtl;
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
if (tv.SelectedNode == null)
return;
if (tv.SelectedNode.Level > 0)
tv.SelectedNode.Parent.Nodes.Remove(tv.SelectedNode);
else
tv.Nodes.Remove(tv.SelectedNode);
};
}
}
public static void AddItem_EditSelect(this ContextMenuStrip menu, Control removeCtl, string text = "批量修改选中格")
{
if (removeCtl is DataGridView || removeCtl is ListBox || removeCtl is CheckedListBox)
{
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
if (removeCtl is DataGridView)
{
var dv = (DataGridView)removeCtl;
var cells = dv.SelectedCells.Cast<DataGridViewCell>();
if (!cells.All(c => c.RowIndex == cells.First().RowIndex))
{
var msg = string.Join("\r\n", cells.Select(c => $"{c.Value}\t{c.RowIndex}\t{c.ColumnIndex}"));
if (MessageBox.Show($"所选格不在同一列,确定修改?\r\n内容\t行号\t列号\r\n{msg}", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
}
var newValue = Interaction.InputBox("输入新内容");
if (string.IsNullOrEmpty(newValue) && cells.Count() > 0 && MessageBox.Show($"新内容为空,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
foreach (var cell in cells)
{
cell.Value = newValue;
}
}
else if (removeCtl is ListBox)
{
var box = (ListBox)removeCtl;
if(box.SelectedIndices?.Count > 1)
{
if (MessageBox.Show($"一共选中 {box.SelectedIndices?.Count } 行,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
}
var newValue = Interaction.InputBox("输入新内容");
if (string.IsNullOrEmpty(newValue) && box.SelectedIndices?.Count > 0 && MessageBox.Show($"新内容为空,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
foreach (int index in box.SelectedIndices)
{
box.Items[index] = newValue;
}
}
else if (removeCtl is CheckedListBox)
{
var box = (CheckedListBox)removeCtl;
if (box.SelectedIndices?.Count > 1)
{
if (MessageBox.Show($"一共选中 {box.SelectedIndices?.Count } 行,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
}
var newValue = Interaction.InputBox("输入新内容");
if (string.IsNullOrEmpty(newValue) && box.SelectedIndices?.Count > 0 && MessageBox.Show($"新内容为空,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
foreach (int index in box.SelectedIndices)
{
box.Items[index] = newValue;
}
}
};
}
else if (removeCtl is TreeView)
{
var tv = (TreeView)removeCtl;
var item = menu.Items.Add(text);
item.Click += (s, e) =>
{
if (tv.SelectedNode == null)
return;
var newValue = Interaction.InputBox("TreeNode 修改有三处需要修改:\r\nText\tName\tToolTipText\r\n用逗号隔开","输入新内容","节点文本,节点名,节点提示文本");
if (string.IsNullOrEmpty(newValue) && MessageBox.Show($"新内容为空,确认修改?", "确认修改", MessageBoxButtons.YesNo) == DialogResult.No)
return;
var arr = newValue.Split(new char[] { ',', ',' }, StringSplitOptions.RemoveEmptyEntries);
for(var i=0;i<arr.Length;i++)
{
switch (i)
{
case 0:
tv.SelectedNode.Text = arr[i];
break;
case 1:
tv.SelectedNode.Name = arr[i];
break;
case 2:
tv.SelectedNode.ToolTipText = arr[i];
break;
}
}
};
}
}
}