ASP.NET GridView TemplateField控件在回发后丢失

ASP.NET GridView TemplateField控件在回发后丢失,asp.net,gridview,Asp.net,Gridview,解决GridView控件和模板字段的问题。我对GridView的定义如下: <asp:GridView ID="gridView" runat="server" ShowFooter="True" onrowdatabound="onRowDataBound" AutoGenerateColumns="False" onrowcreated="onRowCreated" onrowcommand="onRowCommand" onselectedindexchanged="onSelect


解决GridView控件和模板字段的问题。我对GridView的定义如下:

<asp:GridView ID="gridView" runat="server" ShowFooter="True" onrowdatabound="onRowDataBound" AutoGenerateColumns="False" onrowcreated="onRowCreated" onrowcommand="onRowCommand" onselectedindexchanged="onSelectedIndexChanged">
<Columns>
    <asp:CommandField SelectText="cmdSelectRow" ShowSelectButton="True" />
    <asp:TemplateField AccessibleHeaderText="treeController"  HeaderText="">
        <ItemTemplate>
            <asp:ImageButton ID="btnShow" runat="server" ImageUrl="~\\Images\\treePlus.png" CommandName="TreeShow" UseSubmitBehavior="False"/>
            <asp:ImageButton ID="btnHide" runat="server" Visible="False" ImageUrl="~\\Images\\treeMinus.png" CommandName="TreeHide" UseSubmitBehavior="False" />
        </ItemTemplate>
    </asp:TemplateField>
    <asp:BoundField DataField="treeLevel" HeaderText="Tree Level" />
    <asp:BoundField DataField="parentTaskId" HeaderText="parent_task_id" />
    <asp:BoundField DataField="taskId" HeaderText="task_id" />
    <asp:BoundField DataField="groupId" HeaderText="group_id" />
    <asp:BoundField DataField="hasTiming" HeaderText="" />
            ... much more BoundFiels ...</Columns>
    protected void  Page_PreRender(object sender, System.EventArgs e) 
    {
        /* set active view */
        if (IsPostBack == false)
            SetView(tasksMultiView.ActiveViewIndex);
    }
    protected void  SetView (int viewIndex)
    {
        /* declarations */
        Control     viewControl = null;
        View        selectedView = null;
        ListItem    selectedItem = null;
        /* get control */
        selectedView = tasksMultiView.Views[viewIndex];
        selectedItem = View.Items[viewIndex];
        /* get control */
        if ((viewControl = selectedView.FindControl(selectedItem.Value)) != null)
            /* bind data */
            viewControl.DataBind();
    }
如图所示,我正在更改GridView结构(在第一页加载或回发时)

这是自定义控件的DataBind事件,主要目的是将数据绑定到网格:-) 该事件由在父控件的Page_PreRender方法中调用DataBind触发,如下所示:

<asp:GridView ID="gridView" runat="server" ShowFooter="True" onrowdatabound="onRowDataBound" AutoGenerateColumns="False" onrowcreated="onRowCreated" onrowcommand="onRowCommand" onselectedindexchanged="onSelectedIndexChanged">
<Columns>
    <asp:CommandField SelectText="cmdSelectRow" ShowSelectButton="True" />
    <asp:TemplateField AccessibleHeaderText="treeController"  HeaderText="">
        <ItemTemplate>
            <asp:ImageButton ID="btnShow" runat="server" ImageUrl="~\\Images\\treePlus.png" CommandName="TreeShow" UseSubmitBehavior="False"/>
            <asp:ImageButton ID="btnHide" runat="server" Visible="False" ImageUrl="~\\Images\\treeMinus.png" CommandName="TreeHide" UseSubmitBehavior="False" />
        </ItemTemplate>
    </asp:TemplateField>
    <asp:BoundField DataField="treeLevel" HeaderText="Tree Level" />
    <asp:BoundField DataField="parentTaskId" HeaderText="parent_task_id" />
    <asp:BoundField DataField="taskId" HeaderText="task_id" />
    <asp:BoundField DataField="groupId" HeaderText="group_id" />
    <asp:BoundField DataField="hasTiming" HeaderText="" />
            ... much more BoundFiels ...</Columns>
    protected void  Page_PreRender(object sender, System.EventArgs e) 
    {
        /* set active view */
        if (IsPostBack == false)
            SetView(tasksMultiView.ActiveViewIndex);
    }
    protected void  SetView (int viewIndex)
    {
        /* declarations */
        Control     viewControl = null;
        View        selectedView = null;
        ListItem    selectedItem = null;
        /* get control */
        selectedView = tasksMultiView.Views[viewIndex];
        selectedItem = View.Items[viewIndex];
        /* get control */
        if ((viewControl = selectedView.FindControl(selectedItem.Value)) != null)
            /* bind data */
            viewControl.DataBind();
    }
希望对您有所帮助。

您的视图状态在回发时“丢失”,因为您更改了GridView的结构。TemplateField按钮仍然存在,但是…如果在OnInit之后但在GridView数据绑定之前添加/删除列,则不会出现此问题。我认为对于您的问题,在删除列后需要将数据重新绑定到GridView以刷新Viewstate

或者,我也找到了这个可能的解决方案,看起来像是调用myGridView.Columns.Clear();在添加/删除列之前,这可能会对您有所帮助

您的视图状态在回发时“丢失”,因为您更改了GridView的结构。TemplateField按钮仍然存在,但是…如果在OnInit之后但在GridView数据绑定之前添加/删除列,则不会出现此问题。我认为对于您的问题,在删除列后需要将数据重新绑定到GridView以刷新Viewstate

或者,我也找到了这个可能的解决方案,看起来像是调用myGridView.Columns.Clear();在添加/删除列之前,这可能会对您有所帮助


根据您添加到问题中的代码,问题可能是您将数据绑定到GridView太晚,无法正常工作。这应该在页面加载中完成。我认为这里也有一个危险信号,您可以在OnDataBinding中调用TasksTreeView.DataBind(),也可以根据ASP.NET生命周期中的事件在SetView中的自定义控件本身中再次调用DataBind

还有,为什么要在受保护的override void OnDataBinding中再次调用数据绑定。您已经在某处调用了数据绑定以触发OnDataBinding。是否最终通过自定义控件对viewControl.DataBind()的SetView调用触发父页中的受保护重写void OnDataBinding?如果是这种情况,那就是一些复杂的、不可维护的代码,您应该重新构造,使父页面和自定义控件松散耦合,这样您就可以重用自定义控件,而无需开发人员了解自定义控件的内部工作

如果CustomControl没有按您希望的方式工作的公共数据绑定方法,请创建一个新的公共方法,模拟GridView数据绑定的数据绑定参数,然后使用传入的数据参数调用相应的GridView

也许您可以重新构造代码,并一起消除SetView方法。您不应该在自定义控件本身中调用数据绑定。这应该由自定义控件的父用户在调用DataBind时决定。替代自定义控件中的数据绑定:

公共覆盖无效数据绑定() { //…这里有一些实现。。。 base.DataBind()
}

根据您添加到问题中的代码,问题可能是您将数据绑定到GridView太晚,无法正常工作。这应该在页面加载中完成。我认为这里也有一个危险信号,您可以在OnDataBinding中调用TasksTreeView.DataBind(),也可以根据ASP.NET生命周期中的事件在SetView中的自定义控件本身中再次调用DataBind

还有,为什么要在受保护的override void OnDataBinding中再次调用数据绑定。您已经在某处调用了数据绑定以触发OnDataBinding。是否最终通过自定义控件对viewControl.DataBind()的SetView调用触发父页中的受保护重写void OnDataBinding?如果是这种情况,那就是一些复杂的、不可维护的代码,您应该重新构造,使父页面和自定义控件松散耦合,这样您就可以重用自定义控件,而无需开发人员了解自定义控件的内部工作

如果CustomControl没有按您希望的方式工作的公共数据绑定方法,请创建一个新的公共方法,模拟GridView数据绑定的数据绑定参数,然后使用传入的数据参数调用相应的GridView

也许您可以重新构造代码,并一起消除SetView方法。您不应该在自定义控件本身中调用数据绑定。这应该由自定义控件的父用户在调用DataBind时决定。替代自定义控件中的数据绑定:

公共覆盖无效数据绑定() { //…这里有一些实现。。。 base.DataBind()
}

在.aspx页面上将EnableViewState设置为false。我遇到了这个问题,这为我解决了这个问题。

在.aspx页面上将EnableViewState设置为false。我遇到了这个问题,这为我解决了这个问题。

谢谢Brian的回复。但是:我在Page_Init方法上添加/删除列,所以在GridView数据绑定之前,这是不好的。所以我不明白,为什么它不应该工作。。。我在设置gridView结构并且以后不再修改时绑定数据。在我看来,第二种可能的解决方案是变通解决方案。。。我可以试一下,但我想了解,我做错了什么,以及如何正确地做。不过,谢谢。我们会把你的代码贴在后面,这样我就能看到你做错了什么。因为如果在GridView数据绑定之前添加/删除列,则应该查找这些内容。可能是删除了错误的列索引?(第一栏)好的,我会在下一个答案中贴出来。顺便说一句,变通解决方案可行,但无论如何,我想知道我做错了什么:-)Brian,我没有回答我自己的问题,而是编辑了我的原始帖子。我发现GridView上的设置是启用的