Почему мой LinkButton внутри GridView не вызывает событие OnClick?
У меня есть LinkButton внутри GridView (через TemplateField). Что бы я ни пытался, LinkButton не будет вызывать свой обработчик событий. Я пробовал оба:
- Традиционный обработчик событий ("OnClick")
- Обработчик события OnRowCommand на уровне GridView.
В обоих случаях я отлаживал, и он даже не ловит обработчик событий.
Если я переместу LinkButton на страницу (так что его нет в GridView), он будет работать нормально, поэтому я знаю, что синтаксис правильный.
Вот "традиционный" метод:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton Text="Cancel" ID="DeleteButton" CausesValidation="false" OnClick="CancelThis" runat="server" />
</ItemTemplate>
<asp:TemplateField>
Что интересно, если я удалю метод "CancelThis" из кода позади, он выдаст ошибку. Так что я знаю, что он знает о своем обработчике событий, потому что он ищет его при компиляции.
Вот метод RowCommand:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton Text="Cancel" ID="DeleteButton" CausesValidation="false" CommandName="CancelThis" runat="server" />
</ItemTemplate>
<asp:TemplateField>
В этом случае GridView имеет:
OnRowCommand="GridView_RowCommand"
Он постбэк, но никогда не намекает на то, что поднял событие.
Есть идеи, что мне здесь не хватает?
3 ответа
Как вы связываете свой GridView
? Используете ли вы контроль источника данных? Если вы связываете вручную во время Page_Load
, возможно, что поскольку сетка привязывается к каждому циклу, обработчик событий не перехватывает должным образом. Если это так, вы можете попробовать что-то вроде:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
//do binding
}
}
Можете ли вы опубликовать пример кода привязки для разметки?
Если вы действительно хотите вызвать проблему, вы можете подключиться к событию RowDataBound в Grid, найти кнопку вручную и добавить обработчик в коде. Что-то вроде:
фрагмент разметки:
<asp:GridView ID="gvTest" runat="server" OnRowDataBound="gvTest_RowDataBound" />
код позади:
protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
//find button in this row
LinkButton button = e.Row.FindControl("DeleteButton") as button;
if(button != null)
{
button.Click += new EventHandler("DeleteButton_Click");
}
}
}
protected void DeleteButton_Click(object sender, EventArgs e)
{
LinkButton button = (LinkButton)sender;
// do as needed based on button.
}
Я не уверен, какова цель кнопки, но, предполагая, что это кнопка удаления строки, вы можете не захотеть использовать этот подход, так как в обработчике событий у вас нет прямого доступа к рассматриваемой строке, например вы бы использовали RowCommand
событие.
Есть ли причина, по которой вы используете поле "Шаблон"? Против говорят ButtonField
? Если вы используете ButtonField
тогда вы можете подключиться к RowCommand
событие.
фрагмент разметки:
<asp:GridView ID="gvTest" runat="server" OnRowCommand="gvTest_RowCommand">
<columns>
<asp:buttonfield buttontype="Link" commandname="Delete" text="Delete"/>
....
</columns>
</asp:GridView>
код позади:
protected void gvTest_RowCommand(object sender, GridViewCommandEventArgs e)
{
if(e.CommandName == "Delete")
{
//take action as needed on this row, for example
int rowIndex = Convert.ToInt32(e.CommandArgument);
GridViewRow currentRow = (sender as GridView).Rows[rowIndex];
//do something against the row...
}
}
Вы можете обратиться к документации MSDN по некоторым из этих тем:
РЕДАКТИРОВАТЬ:
Чтобы ответить на ваш вопрос о ButtonField - да, я не понимаю, почему вы все еще не можете справиться с кнопочным полем. Вот фрагмент кода, чтобы найти поле кнопки во время привязки данных строки и скрыть ее (не проверено, но я думаю, что это сработает...)
protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//let's assume your buttonfield is in column 1
// (you'd know this based on your markup...)
DataControlFieldCell cell = e.Row.Cells[1] as DataControlFieldCell;
if(cell != null)
{
ButtonField field = cell.ContainingField as ButtonField;
//based on your criteria, show or hide the button
field.Visible = false;
//or
field.Visible = true;
}
}
}
На вашем GridView включено viewstate? Это поймало меня много раз.
<button onclick="window.open('<%#Eval("ReportLinks")%>', '_blank');" title='<%#Eval("ReportLinks")%>'> Link</button>