ASP.NET - Problem with GridView with Dynamic Columns

这一生的挚爱 提交于 2020-01-05 04:49:44

问题


I have a GridView that includes BoundField and TemplateField elements. Some of the TemplateField elements are dynamically generated. For the sake of reference, here is the GridView that I am using

  <asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="False" 
      DataKeyNames="ID" ShowFooter="True" EnableModelValidation="True"
      OnLoad="myGridView_Load" OnRowCommand="myGridView_RowCommand"
      OnRowEditing="myGridView_RowEditing" OnRowDeleting="myGridView_RowDeleting"  
      OnRowCancelingEdit="myGridView_RowCancelingEdit" 
      OnRowUpdating="myGridView_RowUpdating">
      <Columns>
        <asp:BoundField DataField="Number" Visible="true" HeaderText="Test" />
        <asp:TemplateField HeaderText="Number">
          <EditItemTemplate>
            <asp:TextBox ID="tb1" runat="server" Text='<%# Bind("Number") %>' />
          </EditItemTemplate>
          <ItemTemplate>
            <asp:Label ID="lb1" runat="server" Text='<%# Bind("Number") %>' />
          </ItemTemplate>
          <FooterTemplate>
            <asp:TextBox ID="ftb" runat="server" Text="[x]" />
          </FooterTemplate>
        </asp:TemplateField>

        <%-- Dynamically Generated Columns Will Be Inserted Here --%>

        <asp:TemplateField HeaderText="Actions">
          <EditItemTemplate>
            <asp:LinkButton ID="ulb" runat="server" Text="update" CommandName="Update" />
            <asp:LinkButton ID="clb" runat="server" Text="cancel" CommandName="Cancel" />
          </EditItemTemplate>
          <FooterTemplate>
            <asp:LinkButton ID="slb" runat="server" Text="insert"  
              OnClick="saveLinkButton_Click" />
          </FooterTemplate>
          <ItemTemplate>
            <asp:LinkButton ID="elb" runat="server" Text="edit" CommandName="Edit" />
            <asp:LinkButton ID="dlb" runat="server" Text="delete" CommandName="Delete" />
          </ItemTemplate>
        </asp:TemplateField
   </Columns>                                                                                                                    
      <EmptyDataTemplate>
        <table border="0" cellpadding="0" cellspacing="0">
          <tr><td>Number</td></tr>
          <tr>
            <td><asp:TextBox ID="ntb" runat="server" /></td>
            <td><asp:LinkButton ID="slb2" runat="server" Text="save" OnClick="saveLinkButton_Click" /></td>
          </tr>
        </table>
      </EmptyDataTemplate>                                                                                
    </asp:GridView>

When the GridView initially loads, everything is loaded properly. However, anytime I perform a command (edit, insert, delete), all of the data goes away. Oddly, the BoundField values still appear correctly. However, any TemplateField does not seem to get rendered. The code that I am using to work with this GridView is here:

public partial class GridView : System.Web.UI.Page
{
    private List<string> dynamicColumnNames = new List<string>();

    protected void Page_Load(object sender, EventArgs e)
    {
        LoadPageData();
    }

    protected void saveLinkButton_Click(object sender, EventArgs e)
    {
    }

    protected void myGridView_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack == false)
        {
            BindGridData();
        }
    }

    protected void myGridView_RowCommand(object sender, GridViewCommandEventArgs e)
    { }

    protected void myGridView_RowEditing(object sender, GridViewEditEventArgs e)
    {
        myGridView.EditIndex = e.NewEditIndex;
        BindGridData();
    }

    protected void myGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        LoadPageData();
        BindGridData();
    }

    protected void myGridView_RowCancelingEdit(object sender, EventArgs e)
    {
        myGridView.EditIndex = -1;
        BindGridData();
    }

    protected void myGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        myGridView.EditIndex = -1;
        LoadPageData();
        BindGridData();
    }

    private void BindGridData()
    {
        // Create a temporary data source
        DataTable tempData = new DataTable();
        tempData.Columns.Add("ID");
        tempData.Columns.Add("Number");           

        // Dynamically add template columns
        foreach (string columnName in dynamicColumnNames)
        {
            tempData.Columns.Add(columnName);

            TemplateField templateField = new TemplateField();
            templateField.HeaderTemplate = new MyTemplateField(ListItemType.Header, columnName);
            templateField.ItemTemplate = new MyTemplateField(ListItemType.Item, columnName);
            templateField.EditItemTemplate = new MyTemplateField(ListItemType.EditItem, columnName);
            templateField.FooterTemplate = new MyTemplateField(ListItemType.Footer, columnName);
            myGridView.Columns.Insert(2, templateField);
        }

        // Add some phony data
        Random random = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < 10; i++)
        {
            DataRow tempRow = tempData.NewRow();
            tempRow["Number"] = (i + 1);

            foreach (string column in dynamicColumnNames)
                tempRow[column] = random.NextDouble();
            tempData.Rows.Add(tempRow);
        }

        // Bind the data to the grid
        myGridView.DataSource = tempData;
        myGridView.DataBind();
    }

    private void LoadPageData()
    {
        dynamicColumnNames.Add("USA");
        dynamicColumnNames.Add("Japan");
        dynamicColumnNames.Add("Mexico");
    }
}

internal class MyTemplateField : ITemplate
{
    // The type of the list item
    private ListItemType listItemType;

    // The value to use during instantiation
    private string value1 = string.Empty;

    public MyTemplateField(ListItemType listItemType, string value1)
    {
        this.listItemType = listItemType;
        this.value1 = value1;
    }

    public void InstantiateIn(Control container)
    {
        if (listItemType == ListItemType.Item)
        {
            TextBox textBox = new TextBox();
            textBox.ReadOnly = true;
            textBox.DataBinding += new EventHandler(textBox_DataBinding);
            container.Controls.Add(textBox);
        }
        else if (listItemType == ListItemType.EditItem)
        {
            TextBox textBox = new TextBox();
            textBox.DataBinding += new EventHandler(textBox_DataBinding);
            container.Controls.Add(textBox);
        }
        else if (listItemType == ListItemType.Header)
        {
            Literal literal = new Literal();
            literal.Text = value1;
            container.Controls.Add(literal);
        }
        else if (listItemType == ListItemType.Footer)
        {
            TextBox textBox = new TextBox();
            container.Controls.Add(textBox);
        }
    }

    private void textBox_DataBinding(object sender, EventArgs e)
    {
        TextBox textBox = (TextBox)(sender);
        GridViewRow row = (GridViewRow)(textBox.NamingContainer);

        textBox.Text = DataBinder.Eval(row.DataItem, value1).ToString();
    }
}

How do I use commands in a GridView with Dynamically added columns? What is wrong with my code?

Thank you!


回答1:


Dynamically added controls must be added on each post, you can't just add these controls on the first page load. Try removing your BindGridData() from within the Page.IsPostBack == false.



来源:https://stackoverflow.com/questions/1875398/asp-net-problem-with-gridview-with-dynamic-columns

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!