2010-08-04 33 views
0

我有一个嵌套的GridView放置在ListView中。 GridView呈现完全适用于绑定在其数据源中的所有实体。嵌套的GridView不会触发行事件

我的gridview中的每条记录都有两个按钮 - “删除”和“编辑”。我遇到的问题是连接到每个按钮的方法都不会被触发。

我认为这种行为的原因是因为我的ListView的数据绑定只发生在第一页加载,而不是每一个后续的回发。因此,当发生回发时,嵌套的gridview事件再也不会被连接 - 因此我的方法不会被解雇。

这里是我的代码[简化]是这样的:

<asp:ListView ID="uiListView" ... runat="server"> 
    <LayoutTemplate> 
     ... 
    </LayoutTemplate> 
    <ItemTemplate> 
     ... 
     <asp:GridView ID="uiGridView" 
        OnRowDataBound="uiGridView_RowDataBound" 
        OnRowEditing="uiGridView_RowEditing" 
        OnRowDeleting="uiGridView_RowDeleting" runat="server"> 
      <Columns> 
       ... 
       <asp:TemplateField> 
        <ItemTemplate> 
         <asp:Button ID="uiEditRowButton" CausesValidation="false" CommandName="Edit" Text="Edit" runat="server" /> 
         <asp:Button ID="uiRemoveRowButton" CausesValidation="false" CommandName="Delete" Text="Remove" runat="server" /> 
        </ItemTemplate> 
       </asp:TemplateField> 
      </Columns> 
     </asp:GridView> 
     ... 
    </ItemTemplate> 
</asp:ListView> 

代码背后:

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!IsPostBack) { 
     uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 
     uiListView.DataSource = ...; 
     uiListView.DataBind(); 
    } 
} 

// Find a GridView and bind relevant data to it 
private void uiListView_ItemDataBound(object sender, ListViewItemEventArgs e) 
{ 
    if (e.Item.ItemType == ListViewItemType.DataItem) { 
     ListViewDataItem listViewDataItem = (ListViewDataItem) e.Item; 

     GridView uiGridView = (GridView)listViewDataItem.FindControl("uiGridView"); 
     ... 
     uiGridView.DataSource = ...; 
     uiGridView.DataBind(); 
    } 
} 

// For every row being bound to GridView, register the edit and delete 
// buttons as postback controls 
protected void uiGridView_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow) 
    { 
     Control uiEditButton = e.Row.FindControl("uiEditRowButton"); 
     if (uiEditButton != null) { 
      ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiEditButton); 
     } 

     Control uiRemoveRowButton = e.Row.FindControl("uiRemoveRowButton"); 
     if (uiRemoveRowButton != null) { 
      ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiRemoveRowButton); 
     } 
    } 
} 

// Method runs when a GridView's edit button is clicked 
protected void uiGridView_RowEditing(object sender, GridViewEditEventArgs e) 
{ 
    Console.WriteLine('Editing Row...'); 
} 

// Method runs when a GridView's delete button is clicked 
protected void uiGridView_RowDeleting(object sender, GridViewDeleteEventArgs e) 
{ 
    Console.WriteLine('Deleting Row'); 
} 

我试图修改上面的代码,并删除 “的IsPostBack!” 条款,以及事件实际上当点击GridView中的一个按钮时被触发。不过,我觉得每回发一次数据绑定感觉不舒服,认为应该有比这更好的解决方案。

回答

1

我解决了这个问题,但从未更新过这篇文章。因此,对于任何感兴趣的人来说,问题在于 - 按钮事件的布线需要在事件处理程序的RowCreated中完成,而不是RowCommand事件处理程序。

这是为什么?看看什么MSDN不得不说每个两个事件:

GridView.OnRowCreated方法:

之前GridView控件可以呈现, 一个GridViewRow对象必须创建 对于控件中的每一行。当GridView控件中的每个 行都创建为 时,引发RowCreated事件 。这使您可以提供 事件处理方法,该方法执行 自定义例程,例如,在发生此事件时,将 自定义内容添加到行中。

GridView。OnRowDataBound方法:

GridView控件可以呈现之前, 在控制各行必须绑定 到数据源的记录。 RowDataBound事件在 数据行(由GridViewRow 对象表示)绑定到GridView控件的 中的数据时引发。这使您能够提供事件处理方法, 执行自定义例程,例如 修改数据绑定 到该行的值,无论何时发生此事件 。

现在究竟是不是从MSDN写了明确的是:当由两个不同的来源

  1. 从数据源创建的行

    OnRowCreated被触发 - 获取传递当的DataBind调用

  2. 从视图状态 - 在回发,行从视图状态加载,而不是从数据源

因此,当发生回发时,我们需要在每一行再次绑定按钮事件。但是,因为我们在RowCommand中执行事件的连线,所以这些方法永远不会再被调用 - 因为它们只会在DataBind上被触发。我们需要做的是将RowCreated方法中的按钮连接起来,这将在我们首次将数据绑定到GridView时调用,并在每次回发时从GridView的ViewState创建行时调用。

2

我知道这篇文章很旧,但是很晚才发现我的项目正在进行中。我不是专家,但我相信问题在于在Postback中设置了ItemDataBound事件。 Databind()可以保留在Postback语句中,但设置事件需要在外部。在回发时,ItemDataBound事件不再存在,因此GridView事件由于包含在ListView的ItemDataBound事件中而不存在。所以

if (!IsPostBack) { 
    uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 
    uiListView.DataSource = ...; 
    uiListView.DataBind(); 
} 

应该阅读....

uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 

if (!IsPostBack) {   
    uiListView.DataSource = ...; 
    uiListView.DataBind(); 
} 

当代码对控件设置事件背后通常最好是始终设置他们Posback声明之外。当它们在aspx页面上设置时,它将永远存在并不重要。