【问题标题】:Dynamically added controls missing during GridView RowUpdatingGridView RowUpdating 期间缺少动态添加的控件
【发布时间】:2012-02-06 21:05:16
【问题描述】:

我有一个带有 TemplateField 列的 GridView,我将 PlaceHolder 控件放入其中。在 GridView 的 DataBound 事件期间,我动态地将几个 CheckBoxes 添加到 PlaceHolder。这可以正常工作并按预期显示。

我的问题是在 RowUpdating 事件期间 PlaceHolder 不包含任何控件;我的复选框丢失了。我还注意到它们在 RowEditing 事件期间丢失了。

我希望能够在 RowUpdating 事件期间获取 CheckBoxes 的值,以便将它们保存到数据库中。

这是一些示例代码。我已经修剪了很多以减小尺寸,但如果您想查看具体内容,请询问,我很乐意添加更多内容。

HTML:

<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" 
    ondatabound="gridView_DataBound" onrowupdating="gridView_RowUpdating" 
    onrowediting="gridView_RowEditing" DataKeyNames="ID">
    <Columns>
        <asp:TemplateField HeaderText="Countries">
            <ItemTemplate>
                <asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField ShowHeader="False">
            <ItemTemplate>
                <asp:LinkButton ID="editButton" runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:LinkButton ID="updateButton" runat="server" CommandName="Update" Text="Update"></asp:LinkButton>
            </EditItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

后面的代码:

// This method works fine, no obvious problems here.
protected void gridView_DataBound(object sender, EventArgs e)
{
    // Loop through the Holidays that are bound to the GridView
    var holidays = (IEnumerable<Holiday>)gridView.DataSource;
    for (int i = 0; i < holidays.Count(); i++)
    {
        // Get the row the Holiday is bound to
        GridViewRow row = gridView.Rows[i];
        // Get the PlaceHolder control
        var placeHolder = (PlaceHolder)row.FindControl("countriesPlaceHolder");
        // Create a CheckBox for each country and add it to the PlaceHolder
        foreach (Country country in this.Countries)
        {
            bool isChecked = holidays.ElementAt(i).Countries.Any(item => item.ID == country.ID);
            var countryCheckBox = new CheckBox
            {
                Checked = isChecked,
                ID = country.Abbreviation + "CheckBox",
                Text = country.Abbreviation
            };
            placeHolder.Controls.Add(countryCheckBox);
        }
    }
}

protected void gridView_RowEditing(object sender, GridViewEditEventArgs e)
{
    // EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
    var checkBoxControls = gridView.Rows[e.NewEditIndex].FindControl("countriesPlaceHolder").Controls;

    gridView.EditIndex = e.NewEditIndex;
    BindData();
}

protected void gridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    // EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
    var checkBoxControls = ((PlaceHolder)gridView.Rows[e.RowIndex].FindControl("countriesPlaceHolder")).Controls;

    // This is where I'd grab the values from the controls, create an entity, and save the entity to the database.

    gridView.EditIndex = -1;
    BindData();
}

这是我为我的数据绑定方法所遵循的文章:http://www.aarongoldenthal.com/post/2009/04/19/Manually-Databinding-a-GridView.aspx

【问题讨论】:

  • 您是否正确转换占位符变量,例如 PlaceHolder placeHolder = e.Row.FindControl("countriesPlaceHolder") as PlaceHolder;您还需要检查 RowType if( if (e.Row.RowType == DataControlRowType.DataRow) 然后将您的 PlaceHolder 实例代码放在之后.. 试试看..
  • 是的,在我的实际代码中,我确实将它转换为 PlaceHolder。我还按照您的建议对 RowType 进行了检查。感谢您的建议。
  • 我看不到你在哪里检查 RowType..
  • 在 StackOverflow 上也检查这个答案,看看它是否有助于听起来像同样的问题。stackoverflow.com/questions/7343943/…
  • 对不起,我的意思是我的实际代码,而不是我上面发布的示例代码。但是,我刚刚更新了示例代码的gridView_RowUpdating,甚至在我的最后对其进行了测试,但还没有运气。我还检查了链接,但这似乎不是我的问题。我正在处理正确的行;我在调试时验证了这一点。

标签: c# asp.net gridview


【解决方案1】:

您需要在页面加载时调用 BindData() 方法。

“由于控件的工作方式,动态控件或列需要在每次页面加载时重新创建。动态控件不会被保留,因此您必须在每个页面回发时重新加载它们;但是,将为这些保留视图状态控制。”

Cells in gridview lose controls on RowUpdating event

在您链接的文章中,还有一个 ItemTemplate 和一个 EditItemTemplace,因为它们具有不同的显示方式,即只读和可编辑。你的也是一样,所以我认为你可以简化你的设计:

<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" ondatabound="gridView_DataBound">
<Columns>
    <asp:TemplateField HeaderText="Countries">
        <ItemTemplate>
            <asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField ShowHeader="False">
        <ItemTemplate>
            <asp:LinkButton ID="editButton" runat="server" Text="Edit" onclick="editButton_Click" ></asp:LinkButton>
            <asp:LinkButton ID="updateButton" runat="server" Text="Update" onclick="updateButton_Click" ></asp:LinkButton>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>
</asp:GridView>

代码背后:

    protected void gridView_DataBound(object sender, EventArgs e)
    {
        // Loop through the Holidays that are bound to the GridView
        var holidays = (IEnumerable<Holiday>)gridView.DataSource;
        for (int i = 0; i < holidays.Count(); i++)
        {
            // Get the row the Holiday is bound to
            GridViewRow row = gridView.Rows[i];
            // Get the PlaceHolder control
            var placeHolder = (PlaceHolder) row.FindControl("countriesPlaceHolder");
            var countryCheckBox = new CheckBox
                                      {
                                          Checked = true,
                                          ID = "auCheckBox",
                                          Text = "Aus",
                                          Enabled = false
                                      };
            placeHolder.Controls.Add(countryCheckBox);

            var editButton = (LinkButton)row.FindControl("editButton");
            editButton.CommandArgument = i.ToString();
            var updateButton = (LinkButton)row.FindControl("updateButton");
            updateButton.CommandArgument = i.ToString();
            updateButton.Visible = false;
        }
    }

    protected void editButton_Click(object sender, EventArgs e)
    {
        LinkButton editButton = (LinkButton) sender;
        int index = Convert.ToInt32(editButton.CommandArgument);

        GridViewRow row = gridView.Rows[index];
        // Get the PlaceHolder control
        LinkButton updateButton = (LinkButton)row.FindControl("updateButton");
        updateButton.Visible = true;
        editButton.Visible = false;

        CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
        if (checkbox != null)
        {
            checkbox.Enabled = true;
            // Get value and update
        }
    }

    protected void updateButton_Click(object sender, EventArgs e)
    {
        LinkButton updateButton = (LinkButton)sender;
        int index = Convert.ToInt32(updateButton.CommandArgument);

        GridViewRow row = gridView.Rows[index];
        // Get the PlaceHolder control
        LinkButton editButton = (LinkButton)row.FindControl("updateButton");
        editButton.Visible = true;
        updateButton.Visible = false;

        CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
        if (checkbox != null)
        {
            // Get value and update

            checkbox.Enabled = false;
        }
    }

如果您想从一开始就启用它,只需删除启用的检查,您就可以删除您的编辑按钮。

希望对您有所帮助。

【讨论】:

  • 起初我以为我在页面加载期间调用了BindData(),但后来我意识到我只是在非回发期间调用它。我调整了逻辑,只在非回发时调用BindData(),但调用我的代码,在每次加载时添加动态复选框。那成功了!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多