ASP.NET - 带有动态列的GridView问题

时间:2009-12-09 17:13:59

标签: asp.net gridview

我有一个包含BoundField和TemplateField元素的GridView。一些TemplateField元素是动态生成的。为了便于参考,这里是我正在使用的GridView

  <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>

当GridView最初加载时,一切都正确加载。但是,无论何时执行命令(编辑,插入,删除),所有数据都会消失。奇怪的是,BoundField值仍然正确显示。但是,似乎没有渲染任何TemplateField。我用来处理这个GridView的代码在这里:

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();
    }
}

如何在带有动态添加列的GridView中使用命令?我的代码出了什么问题?

谢谢!

1 个答案:

答案 0 :(得分:0)

必须在每个帖子上添加动态添加的控件,您不能只在第一页加载时添加这些控件。尝试从BindGridData()中移除Page.IsPostBack == false