DataGridView DataGridViewButtonColumn не замечает настоящую кнопку
Спасибо за просмотр моего вопроса. У меня есть объект под названием 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
это нужно?
2 ответа
Близко.
Кнопки, надеюсь, находятся в значениях ячеек.
Однако вы не можете щелкнуть их просто так.
Вместо этого вы код 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, чтобы различить кнопки и вызвать соответствующий код.
Это может быть хорошо, но, возможно, вы бы предпочли, чтобы правильные клики запускались автоматически..?
С небольшой Reflection Magic (найденной здесь на 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, г-ну Костикову и анонимному пользователю #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)
, Вот как я это сделал: (немного прочитайте ОП и отрегулируйте нижнюю часть конструктора 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***