Question

I have an asp.net 2.0 page that contains 2 UpdatePanels.

The first panel contains a TreeView control, when I select a node in the three view control it triggers an update of the second UpdatePanel only. This much is behaving correctly.

There are two buttons on the page outside of an update panel (previous/next). These buttons trigger an update of both panels. The behaviour of the buttons is to select the adjacent node in the tree. The first time I click on one of these buttons I get the expected behaviour, and adjacent node is selected and the both panels are updated to reflect this change.

The problem happens when I click any of these buttons again. The selected node of the treeview seems to remember the previously selected node and the buttons act on this node. So the behaviour of the previous/next buttons is to do nothing or jump back two.

Edit - Sample code that demonstrates my problem

The markup

 <asp:UpdatePanel ID="myTreeViewPanel" runat="server">
    <ContentTemplate>
       <asp:TreeView runat="server" ID="myTreeView" OnSelectedNodeChanged="myTreeView_SelectedNodeChanged">
          <SelectedNodeStyle BackColor="#FF8000" />
       </asp:TreeView>
    </ContentTemplate>
    <Triggers>
       <asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click" />
    </Triggers>
 </asp:UpdatePanel>
 <asp:UpdatePanel ID="myLabelPanel" runat="server">
    <ContentTemplate>
       <asp:Label runat="server" ID="myLabel" Text="myLabel"></asp:Label>
    </ContentTemplate>
    <Triggers>
       <asp:AsyncPostBackTrigger ControlID="myTreeView" EventName="SelectedNodeChanged" />
       <asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click" />
    </Triggers>
 </asp:UpdatePanel>
 <asp:Button runat="server" ID="myButton" Text="myButton" OnClick="myButton_Click" />

The code behind

   protected void Page_Load ( object sender, EventArgs e )
   {
      if ( !IsPostBack )
      {
         myTreeView.Nodes.Add( new TreeNode( "Test 1", "Test One" ) );
         myTreeView.Nodes.Add( new TreeNode( "Test 2", "Test two" ) );
         myTreeView.Nodes.Add( new TreeNode( "Test 3", "Test three" ) );
         myTreeView.Nodes.Add( new TreeNode( "Test 4", "Test four" ) );
         myTreeView.Nodes.Add( new TreeNode( "Test 5", "Test five" ) );
         myTreeView.Nodes.Add( new TreeNode( "Test 6", "Test size" ) );
      }
   }
   protected void myTreeView_SelectedNodeChanged ( object sender, EventArgs e )
   {
      UpdateLabel( );
   }
   protected void myButton_Click ( object sender, EventArgs e )
   {
      // here we just select the next node in the three
      int index = myTreeView.Nodes.IndexOf( myTreeView.SelectedNode );
      myTreeView.Nodes[ index + 1 ].Select( );
      UpdateLabel( );
   }
   private void UpdateLabel ( )
   {
      myLabel.Text = myTreeView.SelectedNode.Value;
   }

It is like the viewstate of the tree is not being saved?

Was it helpful?

Solution

From UpdatePanel Control Overview [asp.net]

Controls that Are Not Compatible with UpdatePanel Controls

The following ASP.NET controls are not compatible with partial-page updates, and are therefore not supported inside an UpdatePanel control:

  • TreeView and Menu controls.
  • ...

OTHER TIPS

I think you're right about the AJAX partial page postback that it doesn't update the hidden input __ViewState.

I have the same thing with my update panels when a user navigates back to the pages in my website application form. The normal inputs have updated the viewstate and so their values are repopulated but the state of the controls that were updated with AJAX isn't recorded and so they revert to the default state.

I can fix this problem by saving and restoring the selected node in the pages own view state, by just added these two functions.

protected override object SaveViewState()
{
   ViewState["SelectedNodePath"] = myTreeView.SelectedNode.ValuePath;
   return base.SaveViewState();
}

protected void Page_PreLoad(object sender, EventArgs e)
{
   if (ViewState["SelectedNodePath"] != null)
   {
      TreeNode node = myTreeView.FindNode(ViewState["SelectedNodePath"].ToString());
      if (node != null)
         node.Select();
   }
}

I can't load the selected the node inside LoadViewState() because the tree doesn't have any nodes at that point. So I do it in PreLoad.

It just feels wrong that I have to do this. Am I missing something?

I am facing almost a similar issue. I lose the CheckedNodes collection. I doubt the same technique will solve my issues. Any idea?

Update: I solved the issue to a great extent and used some workarounds. See the details here: TreeView inside UpdatePanel issue - postbacks on check and uncheck of the node's Checkbox and Using TreeView inside AJAX UpdatePanel

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top