【问题标题】:ASP.NET - Problem with GridView with Dynamic ColumnsASP.NET - 带有动态列的 GridView 问题
【发布时间】:2009-12-09 17:13:58
【问题描述】:

我有一个包含 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 中使用动态添加列的命令?我的代码有什么问题?

谢谢!

【问题讨论】:

    标签: asp.net gridview


    【解决方案1】:

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

    【讨论】:

    • 我也是这么想的。不幸的是,这只会导致 ListItemType.Item 子句被执行。但是,不会执行 ListItemType.EditItem 子句。因此,这个提议的解决方案不能解决问题。谢谢你的评论。
    • 有没有更好的方法在gridview中动态填充模板列
    猜你喜欢
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2012-09-23
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多