Freitag, 19. Februar 2010

Silverlight Data Binding with RIA Services

Mittels der WCF RIA Services kann man in seiner Silverlight Applikation jetzt auch seine Daten deklarativ an die Controls binden. Genutzt werden muss hier DomainDataSource von den RIA Controls. Dieses Control kann auf folgende Art und Weise mit/ohne Filterkriterien oder zusätzlichen Gruppierungsmerkmalen definiert werden:

   1: <riaControls:DomainDataSource x:Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
   2:     <riaControls:DomainDataSource.DomainContext>
   3:         <ds:OrganizationContext/>
   4:     </riaControls:DomainDataSource.DomainContext>
   5:     <riaControls:DomainDataSource.SortDescriptors>
   6:         <riaData:SortDescriptor PropertyPath="VacationHours" Direction="Ascending" />
   7:     </riaControls:DomainDataSource.SortDescriptors>
   8:     <riaControls:DomainDataSource.FilterDescriptors>
   9:         <riaData:FilterDescriptorCollection>
  10:             <riaData:FilterDescriptor 
  11:  PropertyPath="VacationHours" 
  12:  Operator="IsGreaterThanOrEqualTo">
  13:                 <riaControls:ControlParameter 
  14:  ControlName="vacationHoursText" 
  15:  PropertyName="Text" 
  16:  RefreshEventName="TextChanged" />
  17:             </riaData:FilterDescriptor>
  18:         </riaData:FilterDescriptorCollection>
  19:     </riaControls:DomainDataSource.FilterDescriptors>
  20: </riaControls:DomainDataSource>
  21: <data:DataGrid Name="dataGrid1" MinHeight="100" IsReadOnly="True" Height="Auto" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />

Das Binding zum Control – im Beispiel ein DataGrid - erfolgt dann auf die gewohnte Art und Weise. Jetzt muss man nur noch den Namespace angeben, welcher den DomainContext zur Verfügung stellt. Dies geschieht durch

xmlns:ds="clr-namespace:HRApp.Web"

Wen der Webservice auf der Web-Seite jetzt entsprechend definiert (mehr dazu weiter unten) dann wird das Grid nun über die GetSalariedEmployees gefüllt.

Doch wo ist der Proxy für den Webservice definiert?

Dies ist bei Nutzung der RIA Services nicht nötig, da diese Klassen alle automatisch generiert werden. Zu finden im Ordner Generated_Code im Client (Silverlight) – Projekt. Dieser sollte natürlich nicht überschrieben werden, da dieser ja bei jeder Änderung der Webservice-Klassen neu erzeugt wird.

Schaubild der RIA Services

Ee707359_RIA_CodeGeneration(en-us,VS_91)

Wenn man ein Projekt zur Repräsentation der middle-tier Projekt mit einer Projekt der Präsentationsschicht (z.B. Silverlight)  mittels der RIA Services verknüpft, werden durch die RIA Services Proxy Klassen für die Client Anwendung basiered auf den Entities und Methoden der middle tier generiert. Man kann auch sogenannte shared-Klassen auf der middle-tier Seite zur Implementierung der Applikationslogik definieren, die dann auch auf der Client-Seite zur Verfügung stehen (Namenskonvention <ServiceName>.shared.cs). Eine Definition von Meta-Klassen zur Definition der Validierungen über DataAnnotations ist auch möglich:

[Required]
[CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")]
public string Gender;

Der Webservice

Damit ein Webservice für die RIA Services verwendet werden kann, muss dieser von einer DomainService-Klasse abgeleitet werden. Im Beispiel ist dies die LinqToEntitiesDomainService-Klasse. Des weiteren ist die Class-Annotation [EnableClientAccess()] erforderlich, weil hierdurch den RIA Services signalisiert wird, dass die Proxy Klassen (siehe oben) generiert werden.

   1: namespace HRApp.Web
   2: {
   3:     using System;
   4:     using System.Collections.Generic;
   5:     using System.ComponentModel;
   6:     using System.ComponentModel.DataAnnotations;
   7:     using System.Data;
   8:     using System.Linq;
   9:     using System.Web.DomainServices;
  10:     using System.Web.DomainServices.Providers;
  11:     using System.Web.Ria;
  12:     using System.Web.Ria.Services;
  13:  
  14:     [EnableClientAccess()]
  15:     public class OrganizationService : LinqToEntitiesDomainService<AdventureWorks_DataEntities>
  16:     {
  17:         public IQueryable<Employee> GetEmployee()
  18:         {
  19:             return this.ObjectContext.Employee.OrderBy(e => e.EmployeeID);
  20:         }
  21:         public IQueryable<Employee> GetSalariedEmployees()
  22:         {
  23:             return this.ObjectContext.Employee.Where(e => e.SalariedFlag == true).OrderBy(e => e.EmployeeID);
  24:         }
  25:  
  26:         public void InsertEmployee(Employee employee)
  27:         {

Weitere Details siehe Client Code Generation.

Keine Kommentare:

Kommentar veröffentlichen