0


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

我想你明白使用这个 gridView 我实现了 treeView ...这两个 ImageButtons 是展开/折叠子项的按钮。

如果我对网格不做任何事情,则工作完美,在 PostBacks 之后发生事件。但是,因为有很多列,我有自定义允许调整定义列的顺序和可见性的 gridView 布局。如果我对 GridView 列执行任何操作(重新排序列,或者只是删除列并将其插入到同一位置),则 PostBack 上的 TemplateField 按钮会丢失。即使我没有对 TemplateField 列定义执行任何操作,而是对 BoundFields 列重新排序,在 PostBack 之后 TemplateField 列也会丢失。

看起来 ViewState 有问题(我不知道)。事实是:
1. 我在 Page_Init 方法上进行 GridView 自定义
2. 我在 Page_PreRender 方法上进行数据绑定(由于某些原因),只有在 NOT PostBack 的情况下

回发后,我看到几个问题解决了 TemplateField 项目的问题,但我没有找到解决方案。

有没有人的想法,应该是哪里的问题?为什么它有效,当gridview结构(列)没有做任何事情并且当同一列被取出并重新插入到网格列中时它不起作用?

感谢您的任何帮助或想法。

为了演示页面的“流程”,我添加了更多细节......
GridView 是我的自定义控件的一部分。

    protected void  Page_Init (object sender, EventArgs e)
    {
       /* customize grid control */
       /* here I load the customization defined by user and change GridView.Columns */
       layoutCustomize(gridControl, accountId);
    }

如图所示,我正在更改 GridView 结构(在第一页加载或回发时)

    protected override void OnDataBinding(EventArgs e)
    {
        /* declarations */
        DbModel.TaskView [] tasks = null;
        DataTable           tasksTable = null;
        /* call parent method */
        base.OnDataBinding(e);
        /* get data */
        if ((tasks = TasksView.Data) != null)
        {
            /* build data table */
            tasksTable = TsGridView.BuildDataTable(TasksTreeView, tasks, typeof(TaskView));
            /* apply filter */
            DataTable viewTable = Filter(tasksTable);
            /* bound the data source to the gird */
            TasksTreeView.DataSource = viewTable;
            TasksTreeView.DataBind();
        }
    }

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

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

希望这有帮助。

4

3 回答 3

3

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

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

http://forums.asp.net/p/1229438/2216336.aspx#2216336

于 2013-10-13T00:07:05.330 回答
1

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

于 2015-10-07T18:41:17.210 回答
0

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

另外,为什么要在受保护的覆盖无效 OnDataBinding 中再次调用 DataBind。您已经在某处调用 DataBind 以触发 OnDataBinding。您是否最终通过自定义控件的 SetView 调用 viewControl.DataBind() 在父页面中触发受保护的覆盖无效 OnDataBinding?如果是这种情况,那就是一些令人费解的、不可维护的代码,您应该重组,以便您的父页面和自定义控件松散耦合,这样您就可以重用自定义控件,而无需开发人员了解自定义控件的内部工作原理。

如果您的 CustomControl 没有按您希望的方式工作的公共 DataBind 方法,则创建一个模仿 GridView DataBind 的 DataBind 参数的新公共方法,然后使用传入的数据参数调用适当的 GridView。

也许您可以重组您的代码并一起消除 SetView 方法。您不应该在自定义控件本身中调用 DataBind。当调用 DataBind 时,这应该取决于自定义控件的父用户。改为在您的自定义控件中覆盖 DataBind:

public override void DataBind() { //...这里的一些实现... base.DataBind() }

于 2013-10-13T03:17:54.523 回答