DataGridView DataGridViewButtonColumn不会注意到一个真正的按钮
本文关键字:一个 按钮 DataGridViewButtonColumn 注意到 DataGridView | 更新日期: 2023-09-27 18:15:55
谢谢你看我的问题。我有一个对象叫做UIChoice
namespace uitest
{
public class UIChoice
{
public String name {get; set;}
public Button yes { get; set; }
}
}
那么我有一个Form1
和一个DataGridView
(我叫它grdChoice
)像这样
namespace uitest
{
public class Form1 : Form
{
public BindingList<UIChoice> Choices = new BindingList<UIChoice>();
public Form1 ()
{
InitializeComponent();
DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn();
colName.HeaderText = "Name:";
colName.Name = "yestext";
colName.DataPropertyName = "name";
grdChoice.Columns.Add(colName);
DataGridViewButtonColumn colYes = new DataGridViewButtonColumn();
colYes.HeaderText = "Yes:";
colYes.Name = "yesbutton";
colYes.DataPropertyName = "yes";
colYes.FlatStyle = FlatStyle.Popup;
grdChoice.Columns.Add(colYes);
grdChoice.DataSource = Choices;
grdChoice.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
grdChoice.Show();
FillData();
}
private void FillData()
{
UIChoice myChoice = new UIChoice();
Button Yes = new Button();
Yes.Click += ((sender, args) =>
{
MessageBox.Show("try this yes works");
});
Yes.Text = "yes";
myChoice.name = "try this";
myChoice.yes = Yes;
Choices.Add(myChoice);
UIChoice myChoiceA = new UIChoice();
Button YesA = new Button();
YesA.Click += ((sender, args) =>
{
MessageBox.Show("try A yes works");
});
YesA.Text = "yes";
myChoiceA.name = "try A";
myChoiceA.yes = YesA;
Choices.Add(myChoiceA);
}
}
}
应该发生的事情(在我的想象中)是DataGridView
应该注意到它是DataGridViewButtonColumn
,并注意到它已经被赋予了一个按钮并使用它。但事实并非如此。对我来说,问题是这是一个替换代码。在现实生活中,UIChoice
对象是用方法强化的,DataGridView
(最初)仅仅是为了取代一个水平递增按钮的手摇面板(变得太"庞大"),可悲的是,正如我所写的,DataGridView
不起作用,即当我构造一个BindingList对象时,它似乎没有"注意"或"关心"我给它一个按钮。我如何让DataGridView
注意到我已经给它发送了它需要的Buttons
?
关闭
按钮,希望在单元格值中。
但是你不能像那样点击它们
相反,您编写grdChoice.CellClick
事件,可能像这样:
if (e.ColumnIndex == yourButtonColumnIndex )
{
Button btn = gradesDataGridView[yourButtonColumnIndex , e.RowIndex].Value as Button;
if (btn != null) buttons_Click(btn, null);
}
这将触发一个公共事件buttons_Click
,您可以使用sender参数来识别按钮并调用适当的代码。
这可能是好的,但也许你宁愿看到正确的点击被自动触发…?
使用一点反射魔法(在CodeProject上找到),这也可以工作:
if (e.ColumnIndex == yourButtonColumnIndex )
{
Button btn = gradesDataGridView[yourButtonColumnIndex , e.RowIndex].Value as Button;
if (btn != null)
{
var handler = (EventHandler)GetDelegate(btn, "EventClick");
if (handler != null) btn.Invoke(handler);
}
}
下面是修改后的代码,用于获取按钮的事件处理程序:
private static object GetDelegate(Control issuer, string keyName)
{
// Get key value for a Click Event
var key = typeof(Control)
.GetField(keyName, BindingFlags.Static | BindingFlags.NonPublic |
BindingFlags.FlattenHierarchy)
.GetValue(null);
var events = typeof(Component)
.GetField("events", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(issuer);
// Find the Find method and use it to search up listEntry for corresponding key
var listEntry = typeof(EventHandlerList)
.GetMethod("Find", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(events, new object[] { key });
// Get handler value from listEntry
var handler = listEntry
.GetType()
.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(listEntry);
return handler;
}
向CodeProject上的家伙致敬,Kostikov先生和匿名用户#2573523为控件添加了更改,而不是组件。
编辑我注意到按钮列没有文本。要显示单个按钮的文本,您需要像这样编写DataGridView_CellFormatting
事件:
private void gradesDataGridView_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == yourBottonColumnIndex )
{
Button btn = gradesDataGridView[yourButtonColumnIndex , e.RowIndex].Value as Button;
if (btn != null) e.Value = btn.Text;
}
}
注意e.Value不是单元格。
谢谢你的回答,由于周末和远离工作,我实际上已经完成了这个4小时后张贴,但被要求等待8小时-尽管如此,你应该有点!:-)(我还借用了你对按钮文本显示的e.value
部分的使用,因为它比我的更优雅!)
好的,所以,我个人,我通过意识到DataGridView
CellClick (DataGridView sender).CurrentCell.Value
实际上是(Button)
来修复它。这就是我是如何做到的:(稍微阅读OP &
Form1
构造函数的底部grdChoice.DataSource = Verdicts;
grdChoice.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
grdChoice.CellClick += grdChoice_CellClick; //<-- add this line ***
grdChoice.Show();
下一部分只监视任何单元格上的任何点击,如果它是一个按钮列,则人为地触发按钮
private void grdChoice_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == grdChoice.Columns["yesbutton"].Index)
{
((Button)((DataGridView)sender).CurrentCell.Value).PerformClick();
}
}
最后一部分是显示按钮文本,我这样做了:
private void grdVerdict_CellFormat(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == grdChoice.Columns["yesbutton"].Index)
{
e.Value = ((Button)grdChoice[e.ColumnIndex, e.RowIndex].Value).Text;
}
}
与此处理程序
grdVerdict.CellFormatting += grdVerdict_CellFormat; //<-- add this line near where the 3 stars are above***