Exemplarische Vorgehensweise: Einführung in RIA Services

Diese exemplarische Vorgehensweise bietet einen Überblick über zahlreiche Funktionen in WCF RIA Services. In dieser exemplarischen Vorgehensweise erstellen Sie eine RIA Services -Anwendung, von der Daten aus Tabellen in der AdventureWorks OLTP-Beispieldatenbank abgerufen werden. Zuerst werden die Daten durch Angabe von LoadOperation abgerufen. Diese Daten werden dann mit dem DomainDataSource-Steuerelement abgerufen. Sie geben Sortierung, Filterung und Paging für das Datendarstellungssteuerelement an und fügen ein DataForm-Steuerelement hinzu, um eine ausführliche Ansicht der Daten zu präsentieren. Sie wenden Validierungsregeln auf die Felder an und ermöglichen dem Benutzer das Bearbeiten von Datenwerten. Sie beschränken den Zugriff auf einen Domänenvorgang auf authentifizierte Benutzer. Schließlich definieren Sie die Zuordnung zwischen zwei verknüpften Tabellen und zeigen die verknüpften Daten an.

TipTipp:
Kürzere exemplarische Vorgehensweisen für die ersten Schritte zum Erstellen einer einfacheren RIA Services -Projektmappe finden Sie unter Exemplarische Vorgehensweise: Erstellen einer RIA Services-Projektmappe oder Exemplarische Vorgehensweise: Verwenden der Silverlight-Geschäftsanwendungsvorlage.

Erforderliche Komponenten

Für diese und die anderen exemplarischen Vorgehensweisen in der WCF RIA Services-Dokumentation müssen zusätzlich zu WCF RIA Services und dem WCF RIA Services-Toolkit mehrere erforderliche Programme installiert und korrekt konfiguriert werden, z. B. Visual Studio 2010, die Silverlight Developer-Laufzeit und das Silverlight-SDK. Zudem müssen Sie SQL Server 2008 R2 Express with Advanced Services installieren und konfigurieren und die AdventureWorks OLTP- und LT-Datenbanken installieren.

Ausführliche Anweisungen für jede dieser erforderlichen Komponenten finden Sie in den Themen unter Erforderliche Komponenten für WCF RIA Services. Folgen Sie den Anweisungen in diesen Themen, bevor Sie mit dieser exemplarischen Vorgehensweise fortfahren, um sicherzustellen, dass beim Ausführen der exemplarischen Vorgehensweisen für RIA Services so wenig Probleme wie möglich auftreten.

Erstellen und Einrichten der Projektmappe

In diesem Abschnitt wird die Projektmappe erstellt und eingerichtet.

So erstellen Sie eine neue WCF RIA Services-Anwendung

  1. Erstellen Sie in Visual Studio 2010 ein neues RIA Services -Projekt, indem Sie Datei, Neu und dann Projekt auswählen.

    Das Dialogfeld Neues Projekt wird angezeigt.

  2. Erweitern Sie im Bereich Installierte Vorlagen den Knoten Visual Basic oder Visual C#, und wählen Sie die Kategorie Silverlight aus.

  3. Wählen Sie die Vorlage Silverlight-Geschäftsanwendung aus, und geben Sie für die Anwendung den Namen HRApp ein.

    RIA_HRAppStart

  4. Klicken Sie auf OK.

    Beachten Sie die Struktur der Projektmappe, die erstellt wird:

    • Die Projektmappe besteht aus zwei Projekten: einem Silverlight-Clientprojekt mit dem Namen HRApp und einem ASP.NET-Webanwendungs-Serverprojekt mit dem Namen HRApp.Web.

    • Die Standardprojektmappe enthält zahlreiche automatisch implementierte Funktionen, einschließlich Navigation, Benutzeranmeldung und -abmeldung sowie Registrierung neuer Benutzer.

    RIA_HRAppStructure

  5. Erstellen Sie die Anwendung, und führen Sie sie aus (F5), und untersuchen Sie die Standardimplementierung.

  6. Schließen Sie den Webbrowser.

So richten Sie die Anwendung ein

  1. Öffnen Sie im Projektmappen-Explorer im Clientprojekt "MainPage.xaml".

  2. Suchen Sie in der XAML-Ansicht den TextBlock mit der Bezeichnung ApplicationNameTextBlock.

    Wie aus dem folgenden Markup hervorgeht, wird der Anwendungsname aus einer Ressource abgerufen.

    <TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}" 
                       Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>
    
  3. Erweitern Sie im Projektmappen-Explorer den Ordner "Assets", und erweitern Sie dann den Ordner "Resources".

  4. Öffnen Sie die Datei "ApplicationStrings.resx".

  5. Ändern Sie die ApplicationName-Ressource in Personalanwendung.

  6. Speichern und schließen Sie die Datei "ApplicationStrings.resx".

  7. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner "Views", klicken Sie auf Hinzufügen und anschließend auf Neues Element.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  8. Wählen Sie in Installierte Vorlagen in der Kategorie Silverlight die Vorlage Silverlight-Seite aus, und nennen Sie sie EmployeeList.xaml.

    RIA_HRAppAddPage

  9. Klicken Sie auf Hinzufügen.

  10. Öffnen Sie "EmployeeList.xaml", wenn die Datei nicht automatisch geöffnet wird.

  11. Fügen Sie folgenden XAML-Code zwischen den <Grid>-Tags hinzu.

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource 
      PageScrollViewerStyle}" >
        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
    
            <TextBlock Text="Employee List" Style="{StaticResource HeaderTextStyle}"/>
    
        </StackPanel>
    </ScrollViewer>
    
  12. Speichern Sie die Datei "EmployeeList.xaml".

  13. Öffnen Sie die Datei "MainPage.xaml".

  14. Fügen Sie dem Seitenanfang eine neue Linkschaltfläche hinzu, indem Sie das folgende XAML zwischen den zwei vorhandenen Linkschaltflächen hinzufügen.

    <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/EmployeeList" TargetName="ContentFrame" Content="Employee List"/>
    
    <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>
    
  15. Führen Sie die Anwendung aus. Rechts oben auf der Seite befindet sich der Link Mitarbeiterliste (zwischen den Links Startseite und Info). Klicken Sie darauf, um im Text der Seite "Mitarbeiterliste" anzuzeigen.

    RIA_HRAppPageView

Anzeigen von Daten

In diesem Abschnitt erstellen Sie für Tabellen in der AdventureWorks-Beispieldatenbank ein ADO.NET Entity Data Model. Anschließend erstellen Sie einen Domänendienst, der die Entitäten verfügbar macht und die Daten im Clientprojekt anzeigt.

So fügen Sie eine Datenquelle hinzu

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt HRApp.Web, klicken Sie auf Hinzufügen, und klicken Sie anschließend auf Neues Element.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie in der Kategorie Daten die Vorlage ADO.NET Entity Data Model aus.

    RIA_HRAppAddEntity

  3. Ändern Sie den Namen in AdventureWorks.edmx, und klicken Sie dann auf Hinzufügen.

    Der Assistent für Entity Data Model wird geöffnet.

  4. Klicken Sie auf der Seite Modellinhalte auswählen auf Aus Datenbank generieren und dann auf Weiter.

  5. Erstellen Sie auf der Seite Wählen Sie Ihre Datenverbindung aus eine Verbindung zur AdventureWorks-Datenbank.

  6. Benennen Sie die Einstellungen der Entitätsverbindung AdventureWorks_DataEntities, und klicken Sie dann auf Weiter.

  7. Erweitern Sie auf der Seite Wählen Sie Ihre Datenbankobjekte aus den Knoten Tabellen.

  8. Markieren Sie die Tabellen Employee, PurchaseOrderDetail und PurchaseOrderHeader jeweils mit einem Häkchen.

  9. Nennen Sie den Modellnamespace AdventureWorks_DataModel, und klicken Sie dann auf Fertig stellen.

    Das Entity Data Model wird im Designer angezeigt.

  10. Erstellen Sie die Projektmappe.

So fügen Sie ein Domänendienstobjekt und eine Abfrage von Daten hinzu

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt HRApp.Web, klicken Sie auf Hinzufügen, und klicken Sie anschließend auf Neues Element.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie in der Kategorie Web die Vorlage Domänendienstklasse aus.

    RIA_HRAppAddService

  3. Nennen Sie das neue Element OrganizationService.

  4. Klicken Sie auf Hinzufügen.

  5. Wählen Sie im Dialogfeld Neue Domänendienstklasse hinzufügen die Optionen Employee, PurchaseOrderDetail und PurchaseOrderHeader aus der Liste "Entitäten" aus, und wählen Sie dann für jede Entität Bearbeitung aktivieren aus.

  6. Stellen Sie sicher, dass die Kontrollkästchen Clientzugriff aktivieren und Zugeordnete Klassen für Metadaten generieren aktiviert werden.

  7. Klicken Sie auf OK.

    Die Dateien "OrganizationService.cs/vb" und "OrganizationService.metadata.cs/vb" werden dem Projekt hinzugefügt.

  8. Öffnen Sie die Datei "OrganizationService.cs/vb".

    Für jede Entität wurde eine Abfrage-, Einfüge-, Update- und Löschmethode erstellt. Eine Abfragemethode wird immer für eine Entität erstellt. Die Einfüge-, die Update- und die Löschmethode wurden hinzugefügt, da Bearbeitung aktivieren ausgewählt wurde.

  9. Passen Sie die GetEmployees()-Abfragemethode an, damit die nach EmployeeID sortierten Mitarbeiter zurückgegeben werden. Ersetzen Sie dazu den generierten Code durch den folgenden Code.

    Public Function GetEmployees() As IQueryable(Of Employee)
        Return Me.ObjectContext.Employees.OrderBy(Function(e) e.EmployeeID)
    End Function
    
    public IQueryable<Employee> GetEmployees()
    {
        return this.ObjectContext.Employees.OrderBy(e => e.EmployeeID);
    }
    
  10. Erstellen Sie die Projektmappe.

    Durch Erstellen der Projektmappe werden der Domänenkontext und die Entitäten im Clientprojekt generiert.

  11. Öffnen Sie die Datei "EmployeeList.xaml".

  12. Ziehen Sie von der Toolbox ein TextBlock-Steuerelement in die Entwurfsansicht, und zwar unmittelbar hinter dem DataGrid-Steuerelement.

    Durch Ziehen eines DataGrid in die Entwurfsansicht wird ein Verweis auf die System.Windows.Controls.Data-Assembly hinzugefügt, und das sdk-Präfix wird dem Seitenelement hinzugefügt.

  13. Ändern Sie die Standardwerte für das DataGrid-Steuerelement, in dem Sie die Eigenschaften Höhe und Breite entfernen und folgende Eigenschaften festlegen: Schreibschutz, automatisches Generieren von Spalten und Mindesthöhe.

    <sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" />
    
  14. Speichern Sie die Datei "EmployeeList.xaml".

  15. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  16. Fügen Sie die folgende using- oder Imports-Anweisung hinzu.

    Imports System.ServiceModel.DomainServices.Client
    
    using HRApp.Web;
    using System.ServiceModel.DomainServices.Client;
    
  17. Instanziieren Sie die OrganizationContext-Klasse, und laden Sie Mitarbeiterdaten, indem Sie der Datei "EmployeeList.xaml.cs/vb" den folgenden Code hinzufügen.

    Die OrganizationContext-Klasse wird automatisch im Clientprojekt auf Grundlage der OrganizationService-Klasse im Serverprojekt generiert.

    Partial Public Class EmployeeList
        Inherits Page
    
        Dim _OrganizationContext As New OrganizationContext
        Public Sub New()
            InitializeComponent()
            Me.dataGrid1.ItemsSource = _OrganizationContext.Employees
            _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery())
        End Sub
    
        'Executes when the user navigates to this page.
        Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
    
        End Sub
    End Class
    
    public partial class EmployeeList : Page
    {
        OrganizationContext _OrganizationContext = new OrganizationContext();
        public EmployeeList()
        {
            InitializeComponent();
            this.dataGrid1.ItemsSource = _OrganizationContext.Employees;
            _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery());
        }
    
        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
    
  18. Führen Sie die Anwendung aus.

  19. Klicken Sie auf den Link Mitarbeiterliste, um das DataGrid anzuzeigen.

    RIA_HRAppDataGrid

So fügen Sie eine benutzerdefinierte Abfrage hinzu

  1. Öffnen Sie im HRApp.Web-Projekt die Datei "OrganizationService.cs/vb".

  2. Fügen Sie eine neue Methode mit der Bezeichnung GetSalariedEmployees hinzu, indem Sie dem Textkörper der Klasse den folgenden Code hinzufügen.

    Public Function GetSalariedEmployees() As IQueryable(Of Employee)
        Return Me.ObjectContext.Employees.Where(Function(e) e.SalariedFlag = True).OrderBy(Function(e) e.EmployeeID)
    End Function
    
    public IQueryable<Employee> GetSalariedEmployees()
    {
        return this.ObjectContext.Employees.Where(e => e.SalariedFlag == true).OrderBy(e => e.EmployeeID);
    }
    
  3. Erstellen Sie die Projektmappe.

  4. Öffnen Sie im Clientprojekt "EmployeeList.xaml.cs/vb".

  5. Ersetzen Sie im Konstruktor den Aufruf zu GetEmployeesQuery() durch einen Aufruf von GetSalariedEmployeesQuery().

    _OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery())
    
    _OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery());
    
  6. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

    Beachten Sie, dass für alle angezeigten Mitarbeiter der SalariedFlag-Wert aktiviert ist. Mitarbeiter mit EmployeeID 1, 2 und 4 werden nicht mehr in der Liste angezeigt, da sie nicht entlohnt werden.

    RIA_HRAppFilteredDataGrid

So fügen Sie eine Domänendatenquelle hinzu

  1. Öffnen Sie die Datei "EmployeeList.xaml".

  2. Ziehen Sie von der Toolbox das DomainDataSource-Steuerelement unmittelbar vor dem DataGrid in die Entwurfsansicht. Die DomainDataSource wird möglicherweise am unteren Rand der Liste der Steuerelemente angezeigt.

    TipTipp:
    Wenn sich das DomainDataSource-Steuerelement nicht in der Toolbox befindet, klicken Sie in der Toolbox mit der rechten Maustaste, und klicken Sie anschließend auf Elemente auswählen. Aktivieren Sie auf der Registerkarte Silverlight-Komponenten das Kontrollkästchen DomainDataSource, und klicken Sie auf OK.

    Wenn Sie das DomainDataSource-Steuerelement in die Entwurfsansicht ziehen, wird für den System.Windows.Controls-Namespace im Page-Element ein Verweis mit dem Präfix riaControls erstellt. Außerdem wird links unten in der Entwurfsansicht ein Datenquellensymbol angezeigt.

  3. Fügen Sie der XAML-Datei die folgende Namespacedeklaration für C#-Projektmappen hinzu.

    xmlns:ds="clr-namespace:HRApp.Web"
    
  4. Fügen Sie der XAML-Datei die folgende Namespacedeklaration für Visual Basic-Projektmappen hinzu.

    xmlns:ds="clr-namespace:HRApp"
    
  5. Nennen Sie das DomainDataSource-Steuerelement employeeDataSource, und legen Sie LoadSize, AutoLoad und die Abfragemethode fest, indem Sie das vorhandene XAML durch das folgende XAML ersetzen.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
    </riaControls:DomainDataSource>
    
  6. Legen Sie DomainContext für DomainDataSource fest, indem Sie das folgende XAML hinzufügen.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
        <riaControls:DomainDataSource.DomainContext>
            <ds:OrganizationContext/>
        </riaControls:DomainDataSource.DomainContext>
    </riaControls:DomainDataSource>
    
  7. Ersetzen Sie DataGrid durch das folgende XAML:

    <sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" Height="Auto" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />
    
  8. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  9. Entfernen Sie im Konstruktor den Code, bzw. kommentieren Sie ihn aus, um die OrganizationContext-Instanz, den Aufruf von GetSalariedEmployeesQuery() und den Code zu instanziieren und um die ItemsSource-Eigenschaft des DataGrid-Steuerelements festzulegen.

    Sie müssen nicht mehr explizit Daten laden, da DomainDataSource dies automatisch übernimmt.

    'Dim _OrganizationContext As New OrganizationContext
    Public Sub New()
        InitializeComponent()
        'Me.dataGrid1.ItemsSource = _OrganizationContext.Employees
        '_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery())
    
    End Sub
    
    //OrganizationContext _OrganizationContext = new OrganizationContext();
    public EmployeeList()
    {
        InitializeComponent();
        //this.dataGrid1.ItemsSource = _OrganizationContext.Employees;
        //_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery());
    }
    
  10. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

    Die Anwendung funktioniert ebenso wie zuvor.

So fügen Sie der Datenquelle Sortierung, Filterung und Paging hinzu

  1. Öffnen Sie die Datei "EmployeeList.xaml".

  2. Fügen Sie in DomainDataSource die folgenden SortDescriptors hinzu, um anzugeben, wie Daten in DataGrid sortiert werden.

    Dieses XAML zeigt, wie die Spalte "VacationHours" in aufsteigender Reihenfolge sortiert wird.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
        <riaControls:DomainDataSource.DomainContext>
            <ds:OrganizationContext/>
        </riaControls:DomainDataSource.DomainContext>
        <riaControls:DomainDataSource.SortDescriptors>
            <riaControls:SortDescriptor PropertyPath="VacationHours" Direction="Ascending" />
        </riaControls:DomainDataSource.SortDescriptors>
    </riaControls:DomainDataSource>
    
  3. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

    Die Daten werden nach "VacationHours" sortiert, und Sie können die Sortierrichtung durch Klicken auf die Spaltenüberschrift ändern.

  4. Öffnen Sie die Datei "EmployeeList.xaml".

  5. Damit der Benutzer durch Angabe eines Werts nach den zurückzugebenden Datensätzen filtern kann, fügen Sie vor DataGrid das folgende XAML hinzu.

    Das XAML fügt ein TextBox-Steuerelement hinzu, damit der Benutzer einen Wert eingeben kann.

    <StackPanel Orientation="Horizontal" 
      HorizontalAlignment="Left">
        <TextBlock VerticalAlignment="Center" 
        Text="Min Vacation Hours Filter" />
        <TextBox x:Name="vacationHoursText" Width="75" 
      FontSize="11" Margin="4" Text="0"/>
    </StackPanel>
    
  6. Fügen Sie in DomainDataSource einen Filterdeskriptor hinzu, der an das zuvor hinzugefügte TextBox-Steuerelement gebunden ist.

    <riaControls:DomainDataSource.FilterDescriptors>
        <riaControls:FilterDescriptor 
             PropertyPath="VacationHours" 
             Operator="IsGreaterThanOrEqualTo"
             IgnoredValue=""
             Value="{Binding ElementName=vacationHoursText, Path=Text}"  >
        </riaControls:FilterDescriptor>
    </riaControls:DomainDataSource.FilterDescriptors>
    
  7. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  8. Geben Sie im Textfeld Min Vacation Hours Filter 70 ein.

    Bei den aufgeführten Mitarbeitern sind die Werte für VacationHours größer oder gleich 70.

    RIA_HRAppVacationFilter

  9. Öffnen Sie die Datei "EmployeeList.xaml".

  10. Ziehen Sie von der Toolbox ein DataPager-Steuerelement, und platzieren Sie es unmittelbar unterhalb von DataGrid.

  11. Legen Sie die Seitengröße auf 5 fest, und legen Sie die Quelle entsprechend der Darstellung im folgenden XAML fest.

    <sdk:DataPager PageSize="5" Source="{Binding Data, ElementName=employeeDataSource}" HorizontalAlignment="Left" />
    
  12. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

    Sie sehen nur 5 Zeilen mit gefilterten Daten pro Seite und Pager-Steuerelemente unter DataGrid.

    RIA_HRAppPagedData

Erstellen einer Master-/Detailansicht

In diesem Abschnitt erstellen Sie mithilfe des DataForm-Steuerelements im Silverlight-Toolkit eine ausführliche Ansicht der Daten. Standardmäßig enthält die Silverlight-Geschäftsanwendungs-Projektvorlage die System.Windows.Controls.Data.DataForm.Toolkit.dll-Binärdatei im Ordner "Libs".

So fügen Sie ein DataForm hinzu

  1. Öffnen Sie die Datei "EmployeeList.xaml".

  2. Fügen Sie die folgende Namespacedeklaration hinzu.

    xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    
  3. Fügen Sie nach dem DataPager-Steuerelement das folgende XAML hinzu, um ein DataForm-Steuerelement hinzuzufügen.

    Dieses XAML legt die DataForm-Attribute fest und gibt die anzuzeigenden Spalten an.

    <dataForm:DataForm x:Name="dataForm1" Header="Employee Information"
            AutoGenerateFields="False" HorizontalAlignment="Left"
            AutoEdit="False" AutoCommit="False" Width="400"
            CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}" Margin="0,12,0,0">
        <dataForm:DataForm.EditTemplate>
            <DataTemplate>
                <StackPanel>
                    <dataForm:DataField Label="Employee ID">
                        <TextBox IsReadOnly="True" 
                  Text="{Binding EmployeeID, Mode=OneWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Login ID">
                        <TextBox Text="{Binding LoginID, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Hire Date">
                        <TextBox Text="{Binding HireDate, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Marital Status">
                        <TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Gender">
                        <TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }"  />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Vacation Hours">
                        <TextBox Text="{Binding VacationHours, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }"  />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Sick Leave Hours">
                        <TextBox Text="{Binding SickLeaveHours, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }"  />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Active">
                        <CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }"  />
                    </dataForm:DataField>
                </StackPanel>
            </DataTemplate>
        </dataForm:DataForm.EditTemplate>
    </dataForm:DataForm>
    
  4. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

    Das DataForm zeigt Details des im DataGrid ausgewählten Elements.

    RIA_HRAppDataForm

Aktualisieren der Datenbank

Wenn Sie das Kontrollkästchen Bearbeitung aktivieren im Dialogfeld Neue Domänendienstklasse aktivieren, werden Methoden in der Domänendienstebene generiert, um die Entität zu aktualisieren, einzufügen und zu löschen. In diesem Abschnitt fügen Sie der Benutzeroberfläche der Mitarbeiterliste Bearbeitungsschaltflächen hinzu, um Benutzern die Ausführung dieser Vorgänge zu ermöglichen.

So aktualisieren Sie einen Datensatz

  1. Öffnen Sie die Datei "EmployeeList.xaml".

  2. Fügen Sie nach dem DataForm-Steuerelement das folgende XAML hinzu, um eine Schaltfläche mit der Bezeichnung "Senden" hinzuzufügen.

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,12,0,0">
        <Button x:Name="submitButton" Width="75" Height="23"  
            Content="Submit" Margin="4,0,0,0" Click="submitButton_Click"/>
    </StackPanel>
    
  3. Geben Sie im DomainDataSource-Steuerelement für das SubmittedChanges-Ereignis einen Ereignishandler an.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True" SubmittedChanges="employeeDataSource_SubmittedChanges">
    
  4. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  5. Fügen Sie den folgenden Ereignishandler für das Schaltflächen-Klickereignis hinzu.

    Die submitButton wird deaktiviert, um zu verhindern, dass der Benutzer die Änderung erneut sendet, während der Vorgang bearbeitet wird.

    Private Sub submitButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        submitButton.IsEnabled = False
        employeeDataSource.SubmitChanges()
    End Sub
    
    private void submitButton_Click(object sender, RoutedEventArgs e)
    {
        submitButton.IsEnabled = false;
        employeeDataSource.SubmitChanges();
    }
    
  6. Fügen Sie einen Ereignishandler für das SubmittedChanges-Ereignis hinzu, der überprüft, ob der Sendevorgang erfolgreich abgeschlossen wurde, und submitButton aktiviert.

    Private Sub employeeDataSource_SubmittedChanges(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SubmittedChangesEventArgs)
        If (e.HasError) Then
            MessageBox.Show(String.Format("Changes were not saved: {0}", e.Error.Message))
            e.MarkErrorAsHandled()
        End If
        submitButton.IsEnabled = True
    End Sub
    
    private void employeeDataSource_SubmittedChanges(object sender, SubmittedChangesEventArgs e)
    {
        if (e.HasError)
        {
            MessageBox.Show(string.Format("Changes were not saved: {0}", e.Error.Message));
            e.MarkErrorAsHandled();
        }
        submitButton.IsEnabled = true;
    }
    
  7. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  8. Wählen Sie einen Mitarbeiter aus, und klicken Sie rechts oben im Datenformular auf das Stiftsymbol, um die Bearbeitung zu aktivieren.

    Sie können jetzt jedes bearbeitbare Feld ändern.

  9. Nehmen Sie Änderungen an den Mitarbeiterdaten vor, und klicken Sie auf OK.

  10. Klicken Sie auf Senden, um die Daten zu speichern.

    Änderungen werden nur dann in der Datenbank auf dem Server gespeichert, wenn Sie auf die Schaltfläche "Senden" klicken.

So fügen Sie einem Domänendienst benutzerdefinierte Methoden hinzu

  1. Öffnen Sie im HRApp.Web-Serverprojekt die Datei "OrganizationService.cs/vb".

  2. Fügen Sie die folgende benutzerdefinierte Methode mit dem Namen ApproveSabbatical hinzu.

    Public Sub ApproveSabbatical(ByVal current As Employee)
        Me.ObjectContext.Employees.AttachAsModified(current)
        current.CurrentFlag = False
    End Sub
    
    public void ApproveSabbatical(Employee current)
    {
        // Start custom workflow here
        this.ObjectContext.Employees.AttachAsModified(current);
        current.CurrentFlag = false;
    }
    
  3. Erstellen Sie die Projektmappe.

  4. Öffnen Sie die Datei "EmployeeList.xaml".

  5. Fügen Sie nach der Schaltfläche "Senden" das folgende XAML hinzu, um eine Schaltfläche mit der Bezeichnung "Approve Sabbatical" (Beurlaubung genehmigen) hinzuzufügen.

    <Button x:Name="approveSabbatical" Width="115" Height="23"  Content="Approve Sabbatical"  Margin="4,0,0,0" Click="approveSabbatical_Click"/>
    
  6. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  7. Fügen Sie den folgenden Ereignishandler für das Schaltflächen-Klickereignis hinzu, durch das der Vorgang der ApproveSabbatical-Domäne aufgerufen wird.

    Private Sub approveSabbatical_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim luckyEmployee As Employee
        luckyEmployee = dataGrid1.SelectedItem
        luckyEmployee.ApproveSabbatical()
        employeeDataSource.SubmitChanges()
    End Sub
    
    private void approveSabbatical_Click(object sender, RoutedEventArgs e)
    {
        Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem);
        luckyEmployee.ApproveSabbatical();
        employeeDataSource.SubmitChanges();
    }
    
  8. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  9. Klicken Sie auf die Schaltfläche Approve Sabbatical. Beachten Sie, dass das Kontrollkästchen "CurrentFlag" für den ausgewählten Mitarbeiter deaktiviert ist.

Validieren von Daten

Das DataForm-Steuerelement kann Validierungsfehler aus der Datenzugriffsebene (DAL) anzeigen. Wenn Sie z. B. einen nicht ganzzahligen Wert im Feld "VacationHours" eingeben, wird ein Validierungsfehler angezeigt. Die folgende Abbildung zeigt ein Beispiel des Validierungsverhaltens.

RIA_HRAppValidation

Wenn Sie das Kontrollkästchen Zugeordnete Klassen für Metadaten generieren im Dialogfeld Neue Domänendienstklasse aktivieren, wird eine Datei, die Metadaten enthält, erstellt. In dieser exemplarischen Vorgehensweise wird die Metadatendatei "OrganizationService.metadata.cs/vb" genannt. In diesem Abschnitt fügen Sie der Datei Validierungsattribute hinzu. Die Validierungsregeln werden in den Client- und Serverprojekten erzwungen.

Sie erstellen außerdem eine Benutzeroberfläche, um das Hinzufügen neuer Mitarbeiterdatensätze zur Datenbank zu ermöglichen. Die Validierungsregeln, die Sie in den vorherigen Abschnitten hinzugefügt haben, werden automatisch in der neuen Benutzeroberfläche angewendet.

So fügen Sie Basisvalidierung hinzu

  1. Öffnen Sie im HRApp.web-Projekt die Datei "OrganizationService.metadata.cs/vb".

  2. Fügen Sie der Gender-Eigenschaft und der VacationHours-Eigenschaft die folgenden Attribute hinzu.

    <Required()> _
    Public Property Gender As String
    
    <Range(0, 70)> _
    Public Property VacationHours As Short
    
    [Required]
    public string Gender { get; set; }
    
    [Range(0, 70)]
    public short VacationHours { get; set; }
    
  3. Erstellen Sie die Projektmappe.

  4. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  5. Wählen Sie einen Mitarbeiter aus, und klicken Sie rechts oben im Datenformular auf das Stiftsymbol, um die Bearbeitung zu aktivieren.

  6. Geben Sie einen Wert im Feld Vacation Hours ein, der nicht innerhalb des gültigen Bereichs (0-70) liegt, und verschieben Sie den Fokus zu einem anderen Steuerelement.

    Für Urlaubsstunden wird ein Validierungsfehler angezeigt.

    RIA_HRAppRangeValidation

  7. Löschen Sie den Wert im Feld Gender, und verschieben Sie den Fokus zu einem anderen Steuerelement.

    Ein Validierungsfehler für die Angabe des Geschlechts wird angezeigt.

So fügen Sie eine benutzerdefinierte Validierung hinzu

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt HRApp.Web, klicken Sie auf Hinzufügen, und klicken Sie anschließend auf Neues Element.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie in der Kategorie Code die Vorlage Codedatei aus.

  3. Nennen Sie das neue Element OrganizationService.shared.cs oder OrganizationService.shared.vb.

    Dateien, die mit .shared.cs oder .shared.vb enden, sind sowohl in den Client- als auch in den Serverprojekten verfügbar. Freigegebene Dateien ermöglichen es Ihnen, die gleiche Validierungsregel in beiden Projekten auszuführen. Nach dem Erstellen der Projektmappe in einem späteren Schritt finden Sie im ausgeblendeten Ordner "Generated_Code" auf dem Client die Datei "OrganizationService.shared.cs/vb".

  4. Klicken Sie auf Hinzufügen.

  5. Um eine benutzerdefinierte Validierungsklasse zu erstellen, mit der die der Gender-Eigenschaft zugewiesenen Werte überprüft werden, fügen Sie der freigegebenen Datei den folgenden Code hinzu.

    Imports System
    Imports System.ComponentModel.DataAnnotations
    
    Public Module GenderValidator
        Public Function IsGenderValid(ByVal gender As String, ByVal context As ValidationContext) As ValidationResult
            If gender = "M" OrElse gender = "m" OrElse gender = "F" OrElse gender = "f" Then
                Return ValidationResult.Success
            Else
                Return New ValidationResult("The Gender field only has two valid values 'M'/'F'", New String() {"Gender"})
            End If
        End Function
    End Module
    
    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace HRApp.Web
    {
        public static class GenderValidator
        {
            public static ValidationResult IsGenderValid(string gender, ValidationContext context)
            {
                if (gender == "M" || gender == "m" || gender == "F" || gender == "f")
                {
                    return ValidationResult.Success;
                }
                else
                {
                    return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
                }
            }
        }
    }
    
  6. Öffnen Sie die Datei "OrganizationService.metadata.cs/vb".

  7. Fügen Sie der Gender-Eigenschaft das folgende benutzerdefinierte Validierungsattribut hinzu.

    <Required()> _
    <CustomValidation(GetType(GenderValidator), "IsGenderValid")> _
    Public Property Gender As String
    
    [CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")]
    [Required]
    public string Gender { get; set; }
    
  8. Erstellen Sie die Projektmappe.

  9. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  10. Wählen Sie einen Mitarbeiter aus, und klicken Sie rechts oben im Datenformular auf das Stiftsymbol, um die Bearbeitung zu aktivieren.

  11. Geben Sie einen Wert im Feld Gender ein, der weder M noch W ist und den Fokus zu einem anderen Steuerelement verschiebt.

    Das Ergebnis der benutzerdefinierten Validierung wird angezeigt.

    RIA_HRAppCustomValidation

Hinzufügen von neuen Datensätzen

In diesem Abschnitt fügen Sie ein Formular hinzu, das dem Benutzer ermöglicht, einen neuen Datensatz in der Tabelle "Employee" zu erstellen.

So fügen Sie einen neuen Datensatz hinzu

  1. Fügen Sie im HRApp-Projekt ein neues Element hinzu.

  2. Wählen Sie in der Kategorie Silverlight die Vorlage Untergeordnetes Silverlight-Fenster aus.

  3. Nennen Sie das neue Element EmployeeRegistrationWindow.xaml.

    RIA_HRAppAddChildWindow

  4. Klicken Sie auf Hinzufügen.

  5. Öffnen Sie die Datei "EmployeeRegistrationWindow.xaml.cs/vb".

  6. Wenn Sie C# verwenden, fügen Sie die folgende using-Anweisung hinzu.

    using HRApp.Web;
    
  7. Fügen Sie eine Eigenschaft für die neue Employee-Entität hinzu, die mit den Benutzerwerten erstellt wird.

    Public Property NewEmployee As Employee
    
    public Employee NewEmployee { get; set; }
    
  8. Öffnen Sie die Datei "EmployeeRegistrationWindow.xaml".

  9. Fügen Sie der Datei "EmployeeRegistrationWindow.xaml" die folgende Namespacedeklaration hinzu, um das DataForm-Steuerelement in diesem Fenster zu verwenden.

    xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    
  10. Fügen Sie der Datei "EmployeeRegistrationWindow.xaml" das folgende DataForm-Steuerelement unmittelbar vor der Schaltfläche "Abbrechen" hinzu.

    <dataForm:DataForm x:Name="addEmployeeDataForm"   AutoGenerateFields="False" AutoCommit="True" AutoEdit="True" CommandButtonsVisibility="None">
        <dataForm:DataForm.EditTemplate>
            <DataTemplate>
                <StackPanel>
                    <dataForm:DataField Label="Login ID">
                        <TextBox Text="{Binding LoginID, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="National ID">
                        <TextBox Text="{Binding NationalIDNumber, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Title">
                        <TextBox Text="{Binding Title, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Marital Status">
                        <TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Gender">
                        <TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Salaried">
                        <CheckBox IsChecked="{Binding SalariedFlag, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }" />
                    </dataForm:DataField>
                    <dataForm:DataField Label="Active">
                        <CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True,  ValidatesOnExceptions=True }" />
                    </dataForm:DataField>
                </StackPanel>
            </DataTemplate>
        </dataForm:DataForm.EditTemplate>
    </dataForm:DataForm>
    
  11. Öffnen Sie die Datei "EmployeeRegistrationWindow.xaml.cs/vb".

  12. Fügen Sie den folgenden Code hinzu, um eine neue Employee-Instanz zu erstellen und entweder das Ausführen eines Commits für die neue Instanz oder den Abbruch des Einfügevorgangs zu regeln.

    Partial Public Class EmployeeRegistrationWindow
        Inherits ChildWindow
    
        Public Sub New()
            InitializeComponent()
            NewEmployee = New Employee
            addEmployeeDataForm.CurrentItem = NewEmployee
            addEmployeeDataForm.BeginEdit()
        End Sub
    
        Public Property NewEmployee As Employee
    
        Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click
            Me.addEmployeeDataForm.CommitEdit()
            Me.DialogResult = True
        End Sub
    
        Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click
            NewEmployee = Nothing
            addEmployeeDataForm.CancelEdit()
            Me.DialogResult = False
        End Sub
    
    End Class
    
    public partial class EmployeeRegistrationWindow : ChildWindow
    {
        public EmployeeRegistrationWindow()
        {
            InitializeComponent();
            NewEmployee = new Employee();
            addEmployeeDataForm.CurrentItem = NewEmployee;
            addEmployeeDataForm.BeginEdit();    
        }
    
        public Employee NewEmployee { get; set; }
    
        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            addEmployeeDataForm.CommitEdit();
            this.DialogResult = true;
        }
    
        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            NewEmployee = null;
            addEmployeeDataForm.CancelEdit();
            this.DialogResult = false;
        }
    }
    
  13. Öffnen Sie die Datei "EmployeeList.xaml".

  14. Fügen Sie zwischen DataPager und DataForm das folgende XAML hinzu, um eine Schaltfläche mit dem Namen addNewEmployee zu erstellen.

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,12,0,0">
        <Button x:Name="addNewEmployee" Width="90" Height="23"  Content="Add Employee"  Margin="4,0,0,0" Click="addNewEmployee_Click"/>
    </StackPanel>
    
  15. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  16. Fügen Sie den folgenden Code hinzu, um das Schaltflächen-Klickereignis zu behandeln und das EmployeeRegistrationWindow anzuzeigen.

    Private Sub addNewEmployee_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim addEmp As New EmployeeRegistrationWindow()
        AddHandler addEmp.Closed, AddressOf addEmp_Closed
        addEmp.Show()
    End Sub
    
    private void addNewEmployee_Click(object sender, RoutedEventArgs e)
    {
        EmployeeRegistrationWindow addEmp = new EmployeeRegistrationWindow();
        addEmp.Closed += new EventHandler(addEmp_Closed);
        addEmp.Show();
    }
    
  17. Fügen Sie die folgende Methode hinzu, um das closed-Ereignis für EmployeeRegistrationWindow zu behandeln.

    Private Sub addEmp_Closed(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim emp As EmployeeRegistrationWindow = sender
        If Not emp.NewEmployee Is Nothing Then
            Dim _OrganizationContext As OrganizationContext = employeeDataSource.DomainContext
            _OrganizationContext.Employees.Add(emp.NewEmployee)
            employeeDataSource.SubmitChanges()
        End If
    End Sub
    
    void addEmp_Closed(object sender, EventArgs e)
    {
        EmployeeRegistrationWindow emp = (EmployeeRegistrationWindow)sender;
        if (emp.NewEmployee != null)
        {
            OrganizationContext _OrganizationContext = (OrganizationContext)(employeeDataSource.DomainContext);
            _OrganizationContext.Employees.Add(emp.NewEmployee);
            employeeDataSource.SubmitChanges();
        }
    }
    
  18. Öffnen Sie die Datei "OrganizationService.cs/vb".

  19. Ändern Sie die InsertEmployee-Methode, indem Sie den folgenden Code hinzufügen.

    Public Sub InsertEmployee(ByVal employee As Employee)
        employee.HireDate = DateTime.Now
        employee.ModifiedDate = DateTime.Now
        employee.VacationHours = 0
        employee.SickLeaveHours = 0
        employee.rowguid = Guid.NewGuid()
        employee.ContactID = 1001
        employee.BirthDate = New DateTime(1967, 3, 18)
    
        If ((employee.EntityState = EntityState.Detached) _
                    = False) Then
            Me.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added)
        Else
            Me.ObjectContext.Employees.AddObject(employee)
        End If
    End Sub
    
    public void InsertEmployee(Employee employee)
    {
        employee.HireDate = DateTime.Now;
        employee.ModifiedDate = DateTime.Now;
        employee.VacationHours = 0;
        employee.SickLeaveHours = 0;
        employee.rowguid = Guid.NewGuid();
        employee.ContactID = 1001;
        employee.BirthDate = new DateTime(1967, 3, 18);
    
        if ((employee.EntityState != EntityState.Detached))
        {
            this.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added);
        }
        else
        {
            this.ObjectContext.Employees.AddObject(employee);
        }
    }
    
  20. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  21. Klicken Sie auf die Schaltfläche Mitarbeiter hinzufügen.

    Das EmployeeRegistrationWindow wird geöffnet.

    RIA_Employee_Registration

  22. Fügen Sie Daten im Fenster hinzu, und aktivieren Sie das Kontrollkästchen Salaried.

  23. Klicken Sie auf OK.

  24. Aktualisieren Sie die Seite, und stellen Sie sicher, dass der neue Mitarbeiter im DataGrid angezeigt wird.

Authentifizieren von Benutzern

In diesem Abschnitt beschränken Sie den Zugriff auf die ApproveSabbatical-Methode auf authentifizierte Benutzer.

So fügen Sie die Authentifizierung hinzu

  1. Öffnen Sie die Datei "OrganizationService.cs/vb".

  2. Fügen Sie das RequiresAuthentication-Attribut der ApproveSabbatical-Methode hinzu.

    Wenn Sie das RequiresAuthentication-Attribut für einen Domänenvorgang übernehmen, stellen Sie sicher, dass nur authentifizierte Benutzer den Vorgang aufrufen können. Wenn ein anonymer Benutzer auf die Schaltfläche Approve Sabbatical (Beurlaubung genehmigen) klickt, wird der Vorgang nicht ausgeführt.

    <RequiresAuthentication()> _
    Public Sub ApproveSabbatical(ByVal current As Employee)
        Me.ObjectContext.Employees.AttachAsModified(current)
        current.CurrentFlag = False
    End Sub
    
    [RequiresAuthentication]
    public void ApproveSabbatical(Employee current)
    {
        // Start custom workflow here
        this.ObjectContext.Employees.AttachAsModified(current);
        current.CurrentFlag = false;
    }
    
  3. Öffnen Sie die Datei "EmployeeList.xaml.cs/vb".

  4. Fügen Sie die folgende using- oder Imports-Anweisung hinzu.

    Imports System.ServiceModel.DomainServices.Client.ApplicationServices
    Imports HRApp.LoginUI
    
    using System.ServiceModel.DomainServices.Client.ApplicationServices;
    using HRApp.LoginUI;
    
  5. Ändern Sie die approveSabbatical_Click-Methode, und fügen Sie einen LoggedIn-Handler hinzu, um zu überprüfen, ob der Benutzer authentifiziert ist.

    Private Sub approveSabbatical_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        If WebContext.Current.User IsNot Nothing AndAlso WebContext.Current.User.IsAuthenticated Then
            Dim luckyEmployee As Employee = dataGrid1.SelectedItem
            luckyEmployee.ApproveSabbatical()
            employeeDataSource.SubmitChanges()
        Else
            AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted
            Dim newWindow As New LoginRegistrationWindow
            newWindow.Show()
        End If
    End Sub
    
    Private Sub Current_LoginCompleted(ByVal sender As Object, ByVal e As AuthenticationEventArgs)
        Dim luckyEmployee As Employee = dataGrid1.SelectedItem
        luckyEmployee.ApproveSabbatical()
        employeeDataSource.SubmitChanges()
        RemoveHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted
    End Sub
    
    private void approveSabbatical_Click(object sender, RoutedEventArgs e)
    {
        if (WebContext.Current.User.IsAuthenticated)
        {
            Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem);
            luckyEmployee.ApproveSabbatical();
            employeeDataSource.SubmitChanges();
        }
        else
        {
            WebContext.Current.Authentication.LoggedIn += Authentication_LoggedIn;
            new LoginRegistrationWindow().Show();
        }
    }
    
    private void Authentication_LoggedIn(object sender, AuthenticationEventArgs e)
    {
        Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem);
        luckyEmployee.ApproveSabbatical();
        employeeDataSource.SubmitChanges();
    
        WebContext.Current.Authentication.LoggedIn -= Authentication_LoggedIn;
    }
    
  6. Führen Sie die Anwendung aus, und klicken Sie auf den Link Mitarbeiterliste.

  7. Wählen Sie einen Mitarbeiterdatensatz aus, und klicken Sie auf die Schaltfläche Approve Sabbatical (Beurlaubung genehmigen).

    Sie werden an das Anmeldefenster umgeleitet.

  8. Klicken Sie auf den Link Jetzt registrieren.

  9. Füllen Sie die Pflichtfelder aus, um ein neues Konto zu erstellen.

  10. Klicken Sie auf OK.

    Sie werden mit diesem Konto angemeldet, und der Name wird in einer Leiste unterhalb der Navigationslinks angezeigt.

Anzeigen von verknüpften Daten

Mit RIA Services können Sie leicht mit Daten aus verknüpften Tabellen arbeiten. In diesem Abschnitt fügen Sie eine neue Silverlight-Seite hinzu und zeigen Daten aus den Tabellen "PurchaseOrderHeader" und "PurchaseOrderDetail" an. Sie können auch die Datenänderungsvorgänge anpassen, damit die verknüpften Daten zusammen geändert werden. Ein Beispiel zum Ändern der Daten in verknüpften Tabellen durch einen Domänenvorgang finden Sie unter Festgelegte Hierarchien.

So zeigen Sie Daten aus verknüpften Tabellen an

  1. Klicken Sie im HRApp-Projekt mit der rechten Maustaste auf den Ordner "Views", klicken Sie auf Hinzufügen und anschließend auf Neues Element.

  2. Fügen Sie eine neue Silverlight-Seite mit dem Namen "PurchaseOrders.xaml" hinzu.

  3. Öffnen Sie die Seite "PurchaseOrders.xaml".

  4. Fügen Sie folgenden XAML-Code zwischen den <Grid>-Tags hinzu.

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource 
      PageScrollViewerStyle}" >
        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
    
            <TextBlock Text="Purchase Orders" Style="{StaticResource HeaderTextStyle}"/>
        </StackPanel>
    </ScrollViewer>
    
  5. Öffnen Sie die Datei "MainPage.xaml".

  6. Fügen Sie nach dem EmployeeList-Link das folgende XAML hinzu, um einen Link auf die Seite "PurchaseOrders" einzuschließen.

    <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>
    
    <HyperlinkButton x:Name="Link4" Style="{StaticResource LinkStyle}" NavigateUri="/PurchaseOrders" TargetName="ContentFrame" Content="Purchase Orders"/>
    
  7. Öffnen Sie die Datei "OrganizationService.metadata.cs/vb".

  8. Fügen Sie der PurchaseOrderDetails-Eigenschaft das Include-Attribut und das Composition-Attribut in der PurchaseOrderHeaderMetadata-Klasse hinzu.

    <Include()> _
    <Composition()> _
    Public Property PurchaseOrderDetails As EntityCollection(Of PurchaseOrderDetail)
    
    [Include]
    [Composition]
    public EntityCollection<PurchaseOrderDetail> PurchaseOrderDetails { get; set; }
    
  9. Öffnen Sie die Datei "OrganizationService.cs/vb".

  10. Ändern Sie die GetPurchaseOrderHeaders-Methode, damit die verknüpften Datensätze in PurchaseOrderDetails auch mit der Abfrage abgerufen werden.

    Public Function GetPurchaseOrderHeaders() As IQueryable(Of PurchaseOrderHeader)
        Return Me.ObjectContext.PurchaseOrderHeaders.Include("PurchaseOrderDetails").OrderBy(Function(p) p.PurchaseOrderID)
    End Function
    
    public IQueryable<PurchaseOrderHeader> GetPurchaseOrderHeaders()
    {
        return this.ObjectContext.PurchaseOrderHeaders.Include("PurchaseOrderDetails").OrderBy(p => p.PurchaseOrderID);
    }
    
  11. Öffnen Sie die Seite "PurchaseOrders.xaml".

  12. Klicken Sie im Menü Daten auf Datenquellen anzeigen, um das Datenquellenfenster zu öffnen.

  13. Ziehen Sie den Knoten PurchaseOrderHeader in die Entwurfsoberfläche für "PurchaseOrders.xaml".

    RIA_Order_Header

    Ein DataGrid mit Spalten aus der Tabelle "PurchaseOrderHeader" wird angezeigt.

  14. Erweitern Sie im Fenster Datenquellen den Knoten PurchaseOrderHeader.

  15. Ziehen Sie den Knoten PurchaseOrderDetails, der sich im Knoten PurchaseOrderHeader befindet, zur Entwurfsoberfläche, direkt unterhalb von DataGrid für PurchaseOrderHeader.

    RIA_Order_Details

    Ein DataGrid mit Spalten aus der Tabelle "PurchaseOrderDetails" wird angezeigt.

  16. Suchen Sie in der XAML-Ansicht die DataGrid-Steuerelemente für PurchaseOrderHeader als auch für PurchaseOrderDetails.

  17. Entfernen Sie die Width=”400”-Eigenschaft aus jedem DataGrid, damit es die verfügbare Breite ausfüllt.

  18. Fügen Sie vor dem PurchaseOrderHeader DataGrid das folgende TextBlock-Steuerelement hinzu, um die Daten zu beschriften.

    <TextBlock Text="Order Headers"></TextBlock>
    
  19. Fügen Sie vor PurchaseOrderDetails DataGrid das folgende TextBlock-Steuerelement hinzu, um die Daten zu beschriften.

    <TextBlock Text="Order Details"></TextBlock>
    
  20. Um die Anzahl von Datensätzen zu beschränken, die abgerufen werden, fügen Sie dem DomainDataSource-Steuerelement den folgenden Filterdeskriptor hinzu.

    <riaControls:DomainDataSource.FilterDescriptors>
        <riaControls:FilterDescriptor PropertyPath="PurchaseOrderID" Operator="IsLessThan" Value="10"></riaControls:FilterDescriptor>
    </riaControls:DomainDataSource.FilterDescriptors>
    

    Nachfolgend wird das vollständige XAML für "PurchaseOrders.xaml" angezeigt.

    <navigation:Page x:Class="HRApp.Views.PurchaseOrders" 
               xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
               mc:Ignorable="d"
               xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               d:DesignWidth="640" d:DesignHeight="480"
               Title="PurchaseOrders Page" 
               xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" 
               xmlns:my="clr-namespace:HRApp.Web" 
               xmlns:sdk="https://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
        <sdk:Page.Resources>
            <CollectionViewSource x:Key="purchaseOrderHeaderPurchaseOrderDetailsViewSource" Source="{Binding Path=Data.PurchaseOrderDetails, ElementName=purchaseOrderHeaderDomainDataSource}" />
        </sdk:Page.Resources>
        <Grid x:Name="LayoutRoot">
            <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource 
              PageScrollViewerStyle}" >
                <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
    
                    <TextBlock Text="Purchase Orders" Style="{StaticResource HeaderTextStyle}"/>
                    <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:PurchaseOrderHeader, CreateList=true}" Height="0" LoadedData="purchaseOrderHeaderDomainDataSource_LoadedData_1" Name="purchaseOrderHeaderDomainDataSource" QueryName="GetPurchaseOrderHeadersQuery" Width="0">
                        <riaControls:DomainDataSource.DomainContext>
                            <my:OrganizationContext />
                        </riaControls:DomainDataSource.DomainContext>
                        <riaControls:DomainDataSource.FilterDescriptors>
                            <riaControls:FilterDescriptor PropertyPath="PurchaseOrderID" Operator="IsLessThan" Value="10"></riaControls:FilterDescriptor>
                        </riaControls:DomainDataSource.FilterDescriptors>
                    </riaControls:DomainDataSource>
                    <TextBlock Text="Order Headers"></TextBlock>
                    <sdk:DataGrid AutoGenerateColumns="False" Height="200" ItemsSource="{Binding ElementName=purchaseOrderHeaderDomainDataSource, Path=Data}" Name="purchaseOrderHeaderDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected">
                        <sdk:DataGrid.Columns>
                            <sdk:DataGridTextColumn x:Name="employeeIDColumn" Binding="{Binding Path=EmployeeID}" Header="Employee ID" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="freightColumn" Binding="{Binding Path=Freight}" Header="Freight" Width="SizeToHeader" />
                            <sdk:DataGridTemplateColumn x:Name="modifiedDateColumn" Header="Modified Date" Width="SizeToHeader">
                                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                    <DataTemplate>
                                        <sdk:DatePicker SelectedDate="{Binding Path=ModifiedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <sdk:DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=ModifiedDate, StringFormat=\{0:d\}}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellTemplate>
                            </sdk:DataGridTemplateColumn>
                            <sdk:DataGridTemplateColumn x:Name="orderDateColumn" Header="Order Date" Width="SizeToHeader">
                                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                    <DataTemplate>
                                        <sdk:DatePicker SelectedDate="{Binding Path=OrderDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <sdk:DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=OrderDate, StringFormat=\{0:d\}}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellTemplate>
                            </sdk:DataGridTemplateColumn>
                            <sdk:DataGridTextColumn x:Name="purchaseOrderIDColumn" Binding="{Binding Path=PurchaseOrderID, Mode=OneWay}" Header="Purchase Order ID" IsReadOnly="True" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="revisionNumberColumn" Binding="{Binding Path=RevisionNumber}" Header="Revision Number" Width="SizeToHeader" />
                            <sdk:DataGridTemplateColumn x:Name="shipDateColumn" Header="Ship Date" Width="SizeToHeader">
                                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                    <DataTemplate>
                                        <sdk:DatePicker SelectedDate="{Binding Path=ShipDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <sdk:DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=ShipDate, StringFormat=\{0:d\}}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellTemplate>
                            </sdk:DataGridTemplateColumn>
                            <sdk:DataGridTextColumn x:Name="shipMethodIDColumn" Binding="{Binding Path=ShipMethodID}" Header="Ship Method ID" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="statusColumn" Binding="{Binding Path=Status}" Header="Status" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="subTotalColumn" Binding="{Binding Path=SubTotal}" Header="Sub Total" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="taxAmtColumn" Binding="{Binding Path=TaxAmt}" Header="Tax Amt" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="totalDueColumn" Binding="{Binding Path=TotalDue}" Header="Total Due" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="vendorIDColumn" Binding="{Binding Path=VendorID}" Header="Vendor ID" Width="SizeToHeader" />
                        </sdk:DataGrid.Columns>
                    </sdk:DataGrid>
                    <TextBlock Text="Order Details"></TextBlock>
                    <sdk:DataGrid AutoGenerateColumns="False" Height="200" ItemsSource="{Binding Source={StaticResource purchaseOrderHeaderPurchaseOrderDetailsViewSource}}" Name="purchaseOrderDetailsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected">
                        <sdk:DataGrid.Columns>
                            <sdk:DataGridTemplateColumn x:Name="dueDateColumn" Header="Due Date" Width="SizeToHeader">
                                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                    <DataTemplate>
                                        <sdk:DatePicker SelectedDate="{Binding Path=DueDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <sdk:DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=DueDate, StringFormat=\{0:d\}}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellTemplate>
                            </sdk:DataGridTemplateColumn>
                            <sdk:DataGridTextColumn x:Name="lineTotalColumn" Binding="{Binding Path=LineTotal}" Header="Line Total" Width="SizeToHeader" />
                            <sdk:DataGridTemplateColumn x:Name="modifiedDateColumn1" Header="Modified Date" Width="SizeToHeader">
                                <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                    <DataTemplate>
                                        <sdk:DatePicker SelectedDate="{Binding Path=ModifiedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <sdk:DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=ModifiedDate, StringFormat=\{0:d\}}" />
                                    </DataTemplate>
                                </sdk:DataGridTemplateColumn.CellTemplate>
                            </sdk:DataGridTemplateColumn>
                            <sdk:DataGridTextColumn x:Name="orderQtyColumn" Binding="{Binding Path=OrderQty}" Header="Order Qty" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="productIDColumn" Binding="{Binding Path=ProductID}" Header="Product ID" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="purchaseOrderDetailIDColumn" Binding="{Binding Path=PurchaseOrderDetailID}" Header="Purchase Order Detail ID" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="purchaseOrderIDColumn1" Binding="{Binding Path=PurchaseOrderID}" Header="Purchase Order ID" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="receivedQtyColumn" Binding="{Binding Path=ReceivedQty}" Header="Received Qty" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="rejectedQtyColumn" Binding="{Binding Path=RejectedQty}" Header="Rejected Qty" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="stockedQtyColumn" Binding="{Binding Path=StockedQty}" Header="Stocked Qty" Width="SizeToHeader" />
                            <sdk:DataGridTextColumn x:Name="unitPriceColumn" Binding="{Binding Path=UnitPrice}" Header="Unit Price" Width="SizeToHeader" />
                        </sdk:DataGrid.Columns>
                    </sdk:DataGrid>
                </StackPanel>
            </ScrollViewer>
        </Grid>
    </navigation:Page>
    
  21. Führen Sie die Anwendung aus, und klicken Sie auf den Link Bestellungen.

  22. Wählen Sie andere Datensätze im PurchaseOrderHeader DataGrid aus.

    Beachten Sie, dass die verknüpften PurchaseOrderDetail-Datensätze automatisch angezeigt werden.

    RIA_Details_and_Header

Nächste Schritte

In dieser exemplarische Vorgehensweise wurden Ihnen zahlreiche der Funktionen in RIA Services vorgestellt. Details zu bestimmten Bereichen finden Sie in den anderen exemplarischen Vorgehensweisen in dieser Dokumentation.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Anzeigen von Daten in einer Silverlight-Geschäftsanwendung
Exemplarische Vorgehensweise: Verwenden des Authentifizierungsdiensts mit der Silverlight-Geschäftsanwendung