2013-10-12 28 views
0


解决了GridView控件和模板字段的问题。我已经定义GridView的是这样的:解决GridView控件和模板字段存在的问题ASP.NET GridView TemplateField控件在回传后丢失

<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是按钮expland /折叠子项。

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

它看起来有一些问题与ViewState(我不知道)。事实是,认为:
1.我让GridView的定制上Page_Init方法
2.我做数据绑定(因为一些原因)上Page_PreRender方法,只是如果不回发

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

有enybody的想法,在哪里应该是问题?为什么它可以工作,什么时候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方法触发数据绑定,就像这样:

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

希望,这帮助。

回答

3

您的Viewstate在回发时“丢失”,因为您已经更改了GridView的结构。 TemplateField按钮仍然存在,但是...如果您在OnInit之后但在GridView绑定数据之前添加/删除列,则不会出现此问题。我认为你的问题,尽管你需要在删除列刷新ViewState后重新绑定数据到GridView。或者,我也发现这个可能的解决方案,看起来像调用myGridView.Columns.Clear();在添加/删除列之前可能会为您做诀窍。

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

+0

谢谢布莱恩的回复。但是:我添加/删除Page_Init方法列,所以在我的GridView是数据绑定之前,它不好。所以我不明白,为什么它不应该工作...我设置gridView结构时绑定数据,稍后不修改。建议的第二种可能的解决方案是在我的眼中解决方案...我可以尝试,但我想了解,我做错了什么,以及如何正确地做到这一点。尽管如此,谢谢。 – 12moyo34

+0

把你的代码放在后面,这样我就可以看到你在做什么“错误”。因为在GridView绑定数据之前应该查找是否添加/删除列。可能你正在删除错误的列索引? (列(i)) –

+0

好的,我会在下一个答案中发布它。顺便说一句,解决方案的解决方案的作品,但无论如何,我想知道我做错了:-) – 12moyo34

0

基于你身后添加到您问题的代码,该问题可能是你来不及GridView控件绑定数据才能正常工作。它应该在Page_Load中完成。我认为这里还有一个红旗,你可以在OnDataBinding中调用TasksTreeView.DataBind(),并根据ASP.NET生命周期中的事件再次在自定义控件本身的SetView中调用DataBind。

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

如果您的CustomControl没有按照您希望的方式工作的公共DataBind方法,那么会创建一个新的Public方法来模仿GridView DataBind的DataBind参数,然后使用传入的data参数调用相应的GridView。

也许你可以重构你的代码,并一起消除SetView方法。您不应该在自定义控件本身中调用DataBind。当DataBind被调用时,这应该由自定义控件的父用户决定。覆盖的DataBind在自定义的控制,而不是:

公共覆盖无效的DataBind(){ //...some这里实现... base.DataBind() }

0

设置的EnableViewState以虚假的.aspx页面。我遇到了这个问题,这为我解决了这个问题。