HierarchyLoadMode "ServerOnDemand" not working with NestedViewTemplate

3 posts, 0 answers
  1. Massimiliano
    Massimiliano avatar
    184 posts
    Member since:
    Oct 2012

    Posted 22 Sep 2013 Link to this post

    I'm trying to exploit the Telerik example here:
    http://demos.telerik.com/aspnet-ajax/grid/examples/hierarchy/nestedviewtemplate/defaultcs.aspx
    The goal is to add editing capabilities to this demo, so in the NestedViewTemplate inside the page views of RadMultiPage I have FormView to present the data.
    I'm facing several little problems even if overall it seems to work well.... I will try to ask help for one issue at a time.
    The first issue I'm facing is that all the details inside the NestedViewTemplate are loaded on page load even if HierarchyLoadMode is set to "Conditional" or "ServerOnDemand".
    I would like, for obvious reasons, to fire the FormView bindings inside the NestedViewTemplate only when the parent row is expanded.

    Any hint? (structure follows)

               <NestedViewTemplate>
    <asp:Panel runat="server" ID="RadGrid1DetailContainer" CssClass="RadGridDetailContainer" Visible="false">
    <telerik:RadTabStrip runat="server" ID="RadGrid1DetailTabStrip" MultiPageID="RadGrid1DetailMultipage1" SelectedIndex="0" CssClass="RadGridTabStrip">
    <Tabs>
    <telerik:RadTab runat="server" Text="Dati utente" PageViewID="RadGrid1DetailRadPageView1">
    </telerik:RadTab>
    <telerik:RadTab runat="server" Text="Anagrafica" PageViewID="RadGrid1DetailRadPageView2">
    </telerik:RadTab>
      <telerik:RadTab runat="server" Text="Altri dati" PageViewID="RadGrid1DetailRadPageView3">
    </telerik:RadTab>
    </Tabs>
    </telerik:RadTabStrip>
    <telerik:RadMultiPage runat="server" ID="RadGrid1DetailMultipage1" SelectedIndex="0" RenderSelectedPageOnly="false">
    <telerik:RadPageView runat="server" ID="RadGrid1DetailRadPageView1" CssClass="RadGridPageView">
    <asp:Label ID="Label1" Font-Bold="true" Font-Italic="true" Text='<%#: Item.UserId%>' runat="server" Visible="false"></asp:Label>
     
    <asp:FormView id="RadGrid1DetailForm1" CssClass="RadGridDetailForm" DataSourceID="UserDetailsObjectDataSource" runat="server" ItemType="Eva.Entities.EvaUser">
    <ItemTemplate>
    <div class="form-horizontal form-stripe" style="padding: 12px;">
    <eva:FormUserDetail ID="FormUserDetail1" Item="<%# Item %>" View="Detail2" runat="server" />
     
    <div class="form-actions">
    <button class="btn btn-primary">
    <i class="icon icon-pencil"></i> Modifica
    </button>
     
    </div>
     
    </div>
     
    </ItemTemplate>
      
    </asp:FormView>
     
    <asp:ObjectDataSource ID="UserDetailsObjectDataSource" runat="server" TypeName="Eva.Bll.Core.EvaUsersManager" DataObjectTypeName="Eva.Entities.EvaUser" SelectMethod="GetById">
    <SelectParameters>
    <asp:ControlParameter ControlID="Label1" PropertyName="Text" Type="Int32" Name="UserId"></asp:ControlParameter>
    </SelectParameters>
    </asp:ObjectDataSource>
    </telerik:RadPageView>
     
    <telerik:RadPageView runat="server" ID="RadGrid1DetailRadPageView2">
     
    </telerik:RadPageView>
    <telerik:RadPageView runat="server" ID="RadGrid1DetailRadPageView3">
     
    </telerik:RadPageView>
    </telerik:RadMultiPage>
    </asp:Panel>
               </NestedViewTemplate>

    Inside RadGrid ItemCommand event I check the ExpandCollapse command to set the panel visibility accordingly

    ' Loads inner forms details when row is expanded
    If e.CommandName = RadGrid.ExpandCollapseCommandName AndAlso TypeOf e.Item Is GridDataItem Then
        DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").Visible = Not e.Item.Expanded
    End If

    To trigger editing (expand the row and set the FormView in edit mode, always inside RadGrid ItemCommand, I linked a button to this and it works as expected

    e.Item.Expanded = True
    DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").Visible = True
    Dim gridFormView As FormView = DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").FindControl("RadGrid1DetailMultipage1").FindControl("RadGrid1DetailRadPageView1").FindControl("RadGrid1DetailForm1")
    gridFormView.ChangeMode(FormViewMode.Edit)

    It seems that setting the panel RadGrid1DetailContainer to Visible="false" didn't help to delay the binding
  2. Massimiliano
    Massimiliano avatar
    184 posts
    Member since:
    Oct 2012

    Posted 23 Sep 2013 Link to this post

    I'm testing alternative solutions. 
    Since I also need a bit more flexiblity in managing FormView data sources, I'm trying to move this in code behind.
    What I did so far is to remove the DataSourceID from FormView inside NestedViewTemplate and add this code to the Item_Command event of the main RadGrid, so that when a row is expanded the FormView is binded to data.

    ' Loads inner forms details when row is expanded
    If e.CommandName = RadGrid.ExpandCollapseCommandName AndAlso TypeOf e.Item Is GridDataItem Then
        DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").Visible = Not e.Item.Expanded
        If Not e.Item.Expanded Then
            Dim gridFormView As FormView = DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").FindControl("RadGrid1DetailMultipage1").FindControl("RadGrid1DetailRadPageView1").FindControl("RadGrid1DetailForm1")
     
            Dim userDetailManager As New EvaVwUserDetailBaseManager
            Dim queryData As New PagedQuery
            queryData.SqlSearchParams = New Dictionary(Of String, Object) From {{"UserId", Convert.ToInt32(DirectCast(e.Item, GridDataItem).GetDataKeyValue("UserId"))}}
     
            gridFormView.DataSource = userDetailManager.GetByQuery(queryData)
            gridFormView.DataBind()
        End If
    End If

    Now I don't have (of course) all the FormView details loaded when the main grid loads as before, but the SQL query is only triggered when I expand a row.
    Now the problem is that the FormView is always empty even if the query is triggered correctly. I suspect that this is because the binding here in the Item_Command of the main RadGrid happens too late, when the FormView has already been created and is empty.
    I checked this adding this lines to FormView 
    <EmptyDataTemplate>
        Form is empty
    </EmptyDataTemplate>

    How could I solve this, so to trigger the binding only on expanded rows and not on all the grid rows even if they are not expanded?
    Wich is the right grid event to check this? I tryed in the ItemDataBound or ItemCreated event but wasn't able to access the FormView inside NestedViewTemplate from there or to access the parent row DataKeyValue for the ID.
    Really need some help thanks
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Massimiliano
    Massimiliano avatar
    184 posts
    Member since:
    Oct 2012

    Posted 23 Sep 2013 Link to this post

    Ok I solved. The solution above was correct (almost). The problem was in the DB View I used wich had a wrong join (INNER JOIN instead of LEFT JOIN) so the results where all null (the second DB table is still empty) and FormView displayed empty template.
    So to recap.... if you want to fire the query for the FormView only when you expand a detail and not for all the RadGrid rows on page load, this is a way to go.
    Another little change to the code is that FormView expects an IList or IEnumerable or such and not a single object of your type of course so I had to add this:
    Protected Sub RadGrid1_ItemCommand(ByVal source As Object, ByVal e As GridCommandEventArgs) Handles RadGrid1.ItemCommand
                If e.CommandName = RadGrid.ExpandCollapseCommandName AndAlso TypeOf e.Item Is GridDataItem Then
                    '    DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").Visible = Not e.Item.Expanded
                    If Not e.Item.Expanded Then
                        Dim gridFormView As FormView = DirectCast(e.Item, GridDataItem).ChildItem.FindControl("RadGrid1DetailContainer").FindControl("RadGrid1DetailMultipage1").FindControl("RadGrid1DetailRadPageView1").FindControl("RadGrid1DetailForm1")
                        Dim primaryKey As Integer = Convert.ToInt32(DirectCast(e.Item, GridDataItem).GetDataKeyValue("UserId"))
     
                        SelectUserDetail(primaryKey, gridFormView)
                    End If
                End If
       End Sub
     
            Private Sub SelectUserDetail(primaryKey As Integer, gridFormView As FormView)
                Dim userDetailManager As New EvaVwUserDetailBaseManager
                Dim users As New List(Of EvaVwUserDetailBase)
                Dim queryData As New PagedQuery
     
                ' Query user and add it to IList object for compatibility with FormView
                queryData.SqlSearchParams = New Dictionary(Of String, Object) From {{"UserId", primaryKey}}
                users.Add(userDetailManager.GetByQuery(queryData))
     
                ' Bind to FormView
                gridFormView.DataSource = users
                gridFormView.DataBind()
            End Sub

    Hope this can help someone else as well trying to implement this scenario ;)
Back to Top