0

感谢您查看我的问题。我有一个对象叫UIChoice

namespace uitest
{
  public class UIChoice
  {
      public String name {get; set;}
      public Button yes { get; set; }      
  }
}

然后我有一个像这样Form1DataGridView(我称之为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应该注意到它是 aDataGridViewButtonColumn并注意到它已被赋予一个 Button 并使用它。但事实并非如此。对我来说问题是这是一个替换代码。在现实生活中,该UIChoice对象被大量方法强化,并且DataGridView(最初)只是为了替换水平递增按钮的手摇面板(变得过于“庞大”),可悲的部分是我写的这DataGridView不起作用即,当我构造一个 BindingList 对象时,它似乎没有“注意到”或“关心”我给它一个按钮..我如何使DataGridView我已经发送它Buttons需要的关心?

4

2 回答 2

1

谢谢你的回答,因为周末不上班,我在发帖后实际上已经完成了这个 4 小时,但被要求等待 8 小时 - 不过你应该有积分!:-) (我还借用了你e.value对按钮文本显示部分的使用,因为它比我的更优雅!)

好的,就我个人而言,我通过意识到DataGridViewCellClick(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***
于 2014-08-04T09:49:04.243 回答
1

关。

按钮,希望在单元格值中。

但是,您不能像那样单击它们。

相反,您对事件进行编码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 不是 cell.Value,而只是显示的文本。

于 2014-08-01T21:43:32.940 回答