Binding Hierarchical RadGrid for ASP.NET Ajax with Telerik OpenAccess ORM

Posted by: the telerik blogs, on 02 Oct 2009 | View original | Bookmarked: 0 time(s)

Eventually developers face the need to use a master-detail hierarchical representation of their data. However most users are not aware that this is extremely easily achieved by using Telerik OpenAccess ORM together with our RadGrid for ASP.NET Ajax. Furthermore it is achieved without writing any code in the code behind!

What will be needed is just one RadGrid and two OpenAccessDataSource controls. The two data source controls will be used to query data from the master and detail tables. In our case we used the Company and Employee tables since a company has many employees.

    public partial class Company
    {
        //The 'no-args' constructor required by OpenAccess. 
        public Company()
        {
        }

        [Telerik.OpenAccess.FieldAlias("companyId")]
        public int CompanyId
        {
            get { return companyId; }
            set { this.companyId = value; }
        }

        [Telerik.OpenAccess.FieldAlias("address")]
        public string Address
        {
            get { return address; }
            set { this.address = value; }
        }

        [Telerik.OpenAccess.FieldAlias("name")]
        public string Name
        {
            get { return name; }
            set { this.name = value; }
        }

        [Telerik.OpenAccess.FieldAlias("employees")]
        public IList<Employee> Employees
        {
            get { return employees; }
        }


    } public partial class Employee
    {
        //The 'no-args' constructor required by OpenAccess. 
        public Employee()
        {
        }

        [Telerik.OpenAccess.FieldAlias("employeeId")]
        public int EmployeeId
        {
            get { return employeeId; }
            set { this.employeeId = value; }
        }

        [Telerik.OpenAccess.FieldAlias("firstName")]
        public string FirstName
        {
            get { return firstName; }
            set { this.firstName = value; }
        }

        [Telerik.OpenAccess.FieldAlias("lastName")]
        public string LastName
        {
            get { return lastName; }
            set { this.lastName = value; }
        }

        [Telerik.OpenAccess.FieldAlias("phone")]
        public string Phone
        {
            get { return phone; }
            set { this.phone = value; }
        }

        [Telerik.OpenAccess.FieldAlias("ssn")]
        public string Ssn
        {
            get { return ssn; }
            set { this.ssn = value; }
        }

        [Telerik.OpenAccess.FieldAlias("company")]
        public Company Company
        {
            get { return company; }
            set { this.company = value; }
        }
        public int EmployeeCompanyId
        {
            get { return company.CompanyId; }            
        }


    }
 
Notice the EmployeeCompanyId property. We will discuss it in a minute as it will make much more sense after we look at the definition of the grid. But first let's see the definition of the two data source controls:
    <telerik:OpenAccessDataSource ID="OpenAccessDataSource1" runat="server" 
            ObjectContextProvider="Model.ObjectScopeProvider1, Model" 
            TypeName="Model.Company">
        </telerik:OpenAccessDataSource>
    </div>
    <telerik:OpenAccessDataSource ID="OpenAccessDataSource2" runat="server" 
        ObjectContextProvider="Model.ObjectScopeProvider1, Model" 
        TypeName="Model.Employee" Where="Company.CompanyId == @Company.CompanyId">
        <WhereParameters>
            <asp:SessionParameter Name="Company.CompanyId" SessionField="CompanyId" />
        </WhereParameters>
    </telerik:OpenAccessDataSource>
 

As you can see the first one queries all objects from the Company table. The second one returns only those employee that match the selected company id. This id is obtained with a session parameter.
Now lets define our grid. First we will need to bind the MasterTableView of the grid to the first data source as we want all the company objects to be displayed there. Then we need to bind the second data source to the details table of the grid in order to be displayed for each company. Here is how it is done:

<telerik:RadGrid ID="RadGrid1" runat="server" 
            DataSourceID="OpenAccessDataSource1" AutoGenerateEditColumn="True" 
            GridLines="None">
<HeaderContextMenu>
<CollapseAnimation Type="OutQuint" Duration="200"></CollapseAnimation>
</HeaderContextMenu>

<MasterTableView AutoGenerateColumns="False" DataKeyNames="CompanyId" 
                DataSourceID="OpenAccessDataSource1" AllowAutomaticUpdates="true">    
    <DetailTables>
        <telerik:GridTableView runat="server" DataSourceID="OpenAccessDataSource2" DataKeyNames="EmployeeId,EmployeeCompanyId" AllowAutomaticUpdates="true">
        <ParentTableRelation>
        <telerik:GridRelationFields DetailKeyField="Company.CompanyId" MasterKeyField="CompanyId" />
        </ParentTableRelation>
        </telerik:GridTableView>
    </DetailTables>
<RowIndicatorColumn>
<HeaderStyle Width="20px"></HeaderStyle>
</RowIndicatorColumn>

<ExpandCollapseColumn Visible="True">
<HeaderStyle Width="20px"></HeaderStyle>
</ExpandCollapseColumn>
    <Columns>
        <telerik:GridBoundColumn DataField="CompanyId" DataType="System.Int32" 
            HeaderText="CompanyId" ReadOnly="True" SortExpression="CompanyId" 
            UniqueName="CompanyId">
        </telerik:GridBoundColumn>
        <telerik:GridBoundColumn DataField="Address" HeaderText="Address" 
            SortExpression="Address" UniqueName="Address">
        </telerik:GridBoundColumn>
        <telerik:GridBoundColumn DataField="Name" HeaderText="Name" 
            SortExpression="Name" UniqueName="Name">
        </telerik:GridBoundColumn>
    </Columns>
</MasterTableView>

<FilterMenu>
    <CollapseAnimation Type="OutQuint" Duration="200"></CollapseAnimation>
</FilterMenu>
 </telerik:RadGrid>
 

The only tricky part here is where you specify which fields will be the data keys, because you cannot really use Company.CompanyID. This is where our EmployeeCompanyId kicks in. Using this property we will "help" the grid to successfully find the correct value required during update.

Now you can just start using the grid. Note that if you would like to delete data you will have to enable Cascading delete for the Employees collection in the company class and everything will work out of the box.

We have defined some animations for expanding and collapsing as well to make RadGrid slicker.

 

I hope you enjoyed this example as much as I did writing it!

Advertisement
Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.
Category: DataSet | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 3380 | Hits: 14

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD