代码中添加GridView列的问题

3
我有一个展示一些文件详细信息的GridView。它有5列,其中包括一个模板字段,其中包含复选框。
在代码后台OnInit中,我添加了一些用于显示额外信息的列,这取决于页面是否需要。代码如下:
 for (int i = 0; i < models.Length && i < 3; i++)
            {
                var model = models[i];

                //Add gridview rows
                BoundField bf = new BoundField();
                bf.DataField = "Attribute" + i;
                bf.HeaderText = model.AttributeName;
                bf.Visible = true;

                gvFiles.Columns.Insert(6 + i, bf);

            }

代码没有问题,我可以获取列。在OnLoad事件中,我将某些数据绑定到gridview,这也很好用。

问题出现在postback时。每当页面创建一个postback时,它就会执行OnInit,然后崩溃,并显示此(“on page”)错误消息:

由于找不到ID为'ctl00$MainContent$gvFiles$ctl02$ctl00'的控件或在postback后将不同的控件分配给相同的ID,因此发生了错误。如果未分配ID,则显式设置引发postback事件的控件的ID属性以避免此错误。

我确定了TemplateField中引起问题的复选框,并给它赋予了一个ID。但是,现在在postback时会发生以下情况:

  1. TemplateFields中的复选框不显示

  2. 其中一列是ImageField,它失去了“控件样式宽度/高度”参数,导致图像变得非常大。

问题仅在postback时发生,删除以编程方式添加列的代码会使一切正常工作。

我该如何解决这个问题?


http://www.codeproject.com/Questions/659792/Add-GridView-Column-Dynamically-ASP-Net - Amir Movahedi
分享更多的ASPX标记和代码后端(您在其中绑定GridView并分配模板)。 - Mikhail
提交回传时模型数量是否会改变? - Clinton
你为什么要使用OnInit()函数?那样做在很多方面都很危险。首先在你的gridview中,先将列定义为隐藏,只有在必要时才显示它们。这一切都可以在DataRowBound()事件中完成。 - Fandango68
5个回答

2

简单来说,我给出一行代码的解决方案

在你的Gridview绑定方法中的Page Load事件中添加!IsPostback

说明:

请参考以下代码示例

PageLoad()
{
BindGridview();
}

Public void BindGridview()
{
//Binding codes and add extra column codes
for (int i = 0; i < models.Length && i < 3; i++)
            {
                var model = models[i];

                //Add gridview rows
                BoundField bf = new BoundField();
                bf.DataField = "Attribute" + i;
                bf.HeaderText = model.AttributeName;
                bf.Visible = true;

                gvFiles.Columns.Insert(6 + i, bf);

            }
}

在页面加载中,您调用了“BindGridview()”方法。每当您的页面加载时,都会创建相同的列字段。

您需要仅在第一次页面加载时调用“BindGridview()”方法。因此,您肯定需要!IsPostBack

请参见下面的代码|或在Page Init事件内部调用此代码

PageLoad()
{
if(!IsPostBack)
{
BindGridview();
}
}

现在,第一次加载页面时会调用BindGridview();方法。

有关“IsPostBack”属性的更多详细信息


没有任何效果。仍然是同样的崩溃。问题发生之前,它甚至没有到达PageLoad。 - user2110845
或者在OnInit事件中调用此函数。 - Ramesh Rajendran

2
您需要在回发时重新创建动态添加的控件。MSDN 建议在 PreInit 事件中创建控件。
PreInit 事件在启动阶段完成后、初始化阶段开始前引发。可用于以下操作:
- 检查 IsPostBack 属性以确定是否首次处理页面。此时还设置了 IsCallback 和 IsCrossPagePostBack 属性。 - 创建或重新创建动态控件。 - 动态设置主控件页。 - 动态设置主题属性。 - 读取或设置配置文件属性值。

0
复选框和图像存在问题,因为 CSS 由于错误而失败。 您遇到的错误是,当您进行回发时,已经有一行包含您先前添加的数据,因此要解决此问题,您需要使用以下代码:
protected void Page_Init(object sender, EventArgs e)
    {


        if (Page.IsPostBack)
        {
         gvFiles.DataBind();

        }

    }

这个问题绝对与CSS无关。 - geedubb
当出现错误时,通常模板会崩溃,这就是我所说的CSS。在这种情况下,当已经有一行内容时,模板会崩溃。databind()会清除并重新绑定gridview,因此即使您进行postback,也不会再出现问题。 - user2530227
@geedubb请花时间仔细阅读答案。发帖人明确表示您的代码存在逻辑问题,导致页面呈现出现故障。 - TCB13
@TCB13 如果您仔细阅读问题,您会发现这不是我提出的问题,也不是我的代码。 - geedubb

0
如果在您的OnInit事件中有一个if(!ispostback),请将其删除。动态控件需要在每个Oninit事件的postback上创建。
如果未重新创建控件,则无法找到它,类似于您的情况发生的情况。 如果在PageLoad上创建控件,则无法访问客户端值,并且会出现不同的错误。
希望这可以帮助您。

0

如果您在Post Back时添加的列数与初始加载时不同,那可能就是问题所在。特别是当视图状态尝试加载时:

当基于某些条件(即,在每个页面访问时不加载它们)向某些父控件p添加动态控件c时,您需要确保将c添加到p的Controls集合的末尾。原因是因为p的视图状态也包含了p的子项的视图状态,并且正如我们将在“解析视图状态”部分中讨论的那样,p的视图状态通过索引指定其子项的视图状态。(图5说明了将动态控件插入到Controls集合的其他位置可能会导致损坏的视图状态。)

http://msdn.microsoft.com/en-us/library/ms972976.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接