Поделиться через


Silverlight toolkit with ADO.NET Data services , Master-Details with Accordion

Download the sample Silverlight project here :

About the Silverlight toolkit  ,

From their Codeplex page : https://silverlight.codeplex.com/

“The Silverlight Toolkit is a collection of Silverlight controls, components and utilities made available outside the normal Silverlight release cycle”

In the first of a series I am planning , we will talk about how to achieve a Master-Child display using the Accordion control 
from the Silverlight Toolkit control.

The data model we will be binding looks like this :

SLToolkitAccordion_DataModel

Type Employee has a property called Department of type Department.
Type Department has a collection of type Employee called Employees.

Employee and Department are related 1..1
Department and Employee are related 1..M

We want to bind the Department names to the header of the Accordion and
the employees as a list inside the content of the accordion.
When we are done , the final output should look like this :

SLTOolkit_Accordionoutput

Configuring the header to show the DepartmentName

The Header template of the Accordion has a textblock which binds to the DepartMentName property of the
Department entity.

  <layoutToolkit:Accordion.HeaderTemplate >
       <DataTemplate>
            <TextBlock Text="{Binding Path=DepartMentName}"></TextBlock>
       </DataTemplate>
 </layoutToolkit:Accordion.HeaderTemplate>

Configuring the content to show the names of the employees working in the department.

The content of the Accordion pane would be a list box which is bound to the Employees collection of the Department

entity type and shows the EmployeeName as the DisplayMember.

 <layoutToolkit:Accordion.ContentTemplate>
      <DataTemplate>
          <ListBox ItemsSource="{Binding Employees}" DisplayMemberPath="EmployeeName">
          </ListBox>
      </DataTemplate>
</layoutToolkit:Accordion.ContentTemplate>

To write the Silverlight client code for this project ,we will need to generate the Client classes with Databinding enabled.

As shown in this article on our team blog .

Once this is done , we have two ways of binding the accordion ,

Eager Loading : Download the employees for a department when you download the departments

Lazy Load : Download the employees for a department when the header of an accordion pane , i.e Department is clicked.

Eager Loading :

 DataServiceQuery<Department> deptQueryWithEmployees = context.Departments.Expand("Employees") as DataServiceQuery<Department>;
deptQueryWithEmployees.QueryAndBind(acDepartments);

Since the query part itself isnt interesting in the context of this blog post , I’ve abstracted away the querying into an extension method ( QueryAndBind ) and will be available as part of the download.

Here , as you can see , we are eager loading the Employees for the departments .

I feel that this is wasteful if you have a large number of departments as this not only increases the amount of data on the wire , but it also means that all the data that comes down the wire will be useful .

For example, if you have about 15 departments and a user may click on 5 or less departments , then downloading employees for all the 15 departments seems inefficient.

Xaml for Eager Loading

 <layoutToolkit:Accordion x:Name="acDepartments" Width="400">
    <layoutToolkit:Accordion.HeaderTemplate >
        <DataTemplate>
            <TextBlock Text="{Binding Path=DepartMentName}"></TextBlock>
        </DataTemplate>
    </layoutToolkit:Accordion.HeaderTemplate>
    <layoutToolkit:Accordion.ContentTemplate>
        <DataTemplate>
            <ListBox ItemsSource="{Binding Employees}" DisplayMemberPath="EmployeeName">
            </ListBox>
        </DataTemplate>
    </layoutToolkit:Accordion.ContentTemplate>
</layoutToolkit:Accordion>

Lazy Loading :
In this case , we will only bind the Headers and  will bind the Employees only if the header is clicked for that department. In the Silverlight Accordion control , the event SelectionChanged is fired when the header of an Accordion Pane is clicked.

By listening to this event , we can find out which department was clicked and load the Employees for that department using BeginLoadProperty .

 public DelayLoad() {
           InitializeComponent();
           context = new TreeViewDataProvider(new Uri("TreeViewDataService.svc", UriKind.RelativeOrAbsolute));
           LoadDepartments();
}
private void LoadDepartments(){
    ((DataServiceQuery<Department>)context.Departments).QueryAndBind(acDepartments);
}

We will subscribe to the SelectionChanged event of the Accordion and add “LoadEmployeesForDepartment” as the event handler.

 private void LoadEmployeesForDepartment(object sender, SelectionChangedEventArgs e)
        {
            //The sender is the control that raised the event
            Accordion acControl = sender as Accordion;
            //Get the Selected Department
            Department selectedDepartment = acControl.SelectedItem as Department;
            if (
                //If the Selected object is department
                selectedDepartment != null 
                && (
                // If the Employees collection is null or empty
                selectedDepartment.Employees == null || selectedDepartment.Employees.Count == 0)
                )
            {
                //Call load property , which updates the Employees collection of this instance 
                //and the UI automatically updates itself, since Department type implements INotifyPropertyChanged
                context.LoadPropertyAndCall<Employee>(selectedDepartment, "Employees",
                    null);
            }

        }

XAML for Delay Load :

 <layoutToolkit:Accordion x:Name="acDepartments" SelectionChanged="LoadEmployeesForDepartment">
    <layoutToolkit:Accordion.HeaderTemplate >
        <DataTemplate>
            <TextBlock Text="{Binding Path=DepartMentName}"></TextBlock>
        </DataTemplate>
    </layoutToolkit:Accordion.HeaderTemplate>
    <layoutToolkit:Accordion.ContentTemplate>
        <DataTemplate>
            <ListBox ItemsSource="{Binding Employees}" DisplayMemberPath="EmployeeName">
            </ListBox>
        </DataTemplate>
    </layoutToolkit:Accordion.ContentTemplate>
</layoutToolkit:Accordion>

Download the sample Silverlight project here :

Running the sample app

  1. Set SLToolkitWithAstoriaWeb as the Start-up project.
  2. Set SLToolkitWithAstoriaTestPage.html as the start-up page.
  3. To run the EagerLoading sample , just hit F5
  4. To run the DelayLoad sample , follow a-c and add the Query string ?delayLoad to the address bar in the browser that comes up.

Comments