Пошаговое руководство. Сбор общих сведений о службах полнофункционального интернет-приложения

Данное пошаговое руководство содержит обзор многих функций Службы WCF RIA. В этом пошаговом руководстве вы создадите приложение Службы RIA , которое извлекает данные из таблиц образца базы данных AdventureWorks OLTP. Сначала необходимо извлечь данные, указав операцию LoadOperation. Затем эти данные нужно будет извлечь с помощью элемента управления DomainDataSource. Мы укажем сортировку, фильтрацию и разбиение на страницы для элемента управления представлением данных, а также добавим элемент управления DataForm для представления подробного вида данных. Применим к полям правила проверки и позволим пользователю изменять значения данных. Затем мы ограничим доступ к операции домена пользователями, прошедшими проверку подлинности. Наконец, определим связь между двумя связанными таблицами и отобразим связанные данные.

TipСовет.
Более короткие пошаговые руководства для начала работы путем создания более базового решения Службы RIA см. в разделе Пошаговое руководство. Создание служб полнофункционального интернет-приложения и доступ к ним или Пошаговое руководство. Использование шаблона бизнес-приложения Silverlight.

Предварительные требования

Для использования этого и других пошаговых руководств, представленных в документации Службы WCF RIA, необходимо установить и правильно настроить ряд обязательных программ, таких как среда выполнения Visual Studio 2010 и пакет SDK Silverlight, а также Службы WCF RIA и набор средств Службы WCF RIA. Для их использования также необходимо установить и настроить SQL Server 2008 R2, экспресс-выпуск с дополнительными службами, и установить базы данных AdventureWorks OLTP и LT.

Подробные инструкции по выполнению каждого из этих предварительных требований приведены в разделах узла Основные компоненты для службы WCF полнофункционального интернет-приложения. До начала использования этого пошагового руководства необходимо выполнить приведенные ниже инструкции, что позволит уменьшить количество проблем, которые могут возникнуть при выполнении шагов, описанных в руководствах Службы RIA .

Создание и настройка решения

В этом разделе вы создадите и настроите решение.

Создание нового приложения служб WCF полнофункционального интернет-приложения

  1. В Visual Studio 2010 создайте новый проект Службы RIA , выбрав в меню пункты Файл, Создать, а затем Проект.

    Откроется диалоговое окно Создать проект.

  2. В области Установленные шаблоны разверните узел Visual Basic или Visual C# и выберите категорию Silverlight.

  3. Выберите шаблон Бизнес-приложение Silverlight и задайте для приложения имя HRApp.

    RIA_HRAppStart

  4. Нажмите кнопку ОК.

    Обратите внимание на структуру создаваемого решения.

    • Решение состоит из двух проектов: клиентского проекта Silverlight с именем HRApp и серверного проекта веб-приложения ASP.NET с именем HRApp.Web.

    • По умолчанию это решение содержит много автоматически реализованных функций, включая навигацию, вход и выход пользователей и регистрацию новых пользователей.

    RIA_HRAppStructure

  5. Постройте и запустите (F5) приложение и исследуйте реализацию по умолчанию.

  6. Закройте веб-обозреватель.

Настройка приложения

  1. В Обозревателе решений из клиентского проекта откройте файл MainPage.xaml.

  2. В представлении XAML найдите ресурс TextBlock с именем ApplicationNameTextBlock.

    Как показано в следующем примере разметки, обратите внимание, что имя приложения извлекается из ресурса.

    <TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}" 
                       Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>
    
  3. В Обозревателе решений разверните папку Assets, а затем разверните папку Resources.

  4. Откройте файл ApplicationStrings.resx.

  5. Измените ресурс ApplicationName (имя приложения) на Приложение HR.

  6. Сохраните и закройте файл ApplicationStrings.resx.

  7. В Обозревателе решений щелкните правой кнопкой мыши папку Views, выберите команду Добавить, а затем пункт Новый элемент.

    Откроется диалоговое окно Добавление нового элемента.

  8. Выберите шаблон Страница Silverlight из категории Silverlight в списке Установленные шаблоны и назовите его EmployeeList.xaml.

    RIA_HRAppAddPage

  9. Нажмите кнопку Добавить.

  10. Откройте файл EmployeeList.xaml, если он не открывается автоматически.

  11. Добавьте следующий XAML-код между тегами <Grid>.

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource 
      PageScrollViewerStyle}" >
        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
    
            <TextBlock Text="Employee List" Style="{StaticResource HeaderTextStyle}"/>
    
        </StackPanel>
    </ScrollViewer>
    
  12. Сохраните файл EmployeeList.xaml.

  13. Откройте файл MainPage.xaml.

  14. Добавьте новую кнопку гиперссылки в верхней части страницы, добавив следующий XAML-код между двумя существующими кнопками гиперссылок.

    <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/EmployeeList" TargetName="ContentFrame" Content="Employee List"/>
    
    <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>
    
  15. Запустите приложение и обратите внимание на новую ссылку Список сотрудников в правом верхнем углу страницы между ссылками В начало и О программе. Щелкните ее, чтобы отобразить «Список сотрудников» в основной части страницы.

    RIA_HRAppPageView

Отображение данных

В этом разделе вы создадите модель ADO.NET EDM для таблиц образца базы данных AdventureWorks. Затем создадите службу домена, предоставляющую сущности и отображающую соответствующие данные в клиентском проекте.

Добавление источника данных

  1. В Обозревателе решений щелкните правой кнопкой мыши проект HRApp.Web, выберите Добавить, а затем Новый элемент.

    Откроется диалоговое окно Добавление нового элемента.

  2. В категории Данные выберите шаблон Модель ADO.NET EDM.

    RIA_HRAppAddEntity

  3. Измените имя на AdventureWorks.edmx и нажмите кнопку Добавить.

    Откроется Мастер моделей EDM.

  4. На странице Выбор содержимого модели щелкните Создать из базы данных и нажмите кнопку Далее.

  5. На странице Выбор подключения к данным создайте соединение с базой данных AdventureWorks.

  6. Присвойте параметрам соединения сущности имя AdventureWorks_DataEntities, а затем нажмите кнопку Далее.

  7. Разверните узел Таблицы на странице Выбор объектов базы данных.

  8. Добавьте галочки рядом с таблицами Employee, PurchaseOrderDetail и PurchaseOrderHeader.

  9. Назовите пространство имен модели AdventureWorks_DataModel и нажмите кнопку Готово.

    В конструкторе отобразится модель EDM.

  10. Создайте решение.

Добавление объекта службы домена и запрос данных

  1. В Обозревателе решений щелкните правой кнопкой мыши проект HRApp.Web, выберите Добавить, а затем Новый элемент.

    Откроется диалоговое окно Добавление нового элемента.

  2. В категории Web выберите шаблон Класс службы домена.

    RIA_HRAppAddService

  3. Назовите новый элемент OrganizationService.

  4. Нажмите кнопку Добавить.

  5. В диалоговом окне Добавление нового класса службы домена выберите из списка «Сущности» элементы Employee, PurchaseOrderDetail и PurchaseOrderHeader, а затем выберите Включить редактирование для каждой сущности.

  6. Убедитесь, что установлены флажки Разрешить клиентский доступ и Сформировать связанные классы для метаданных.

  7. Нажмите кнопку ОК.

    В проект будут добавлены файлы OrganizationService.cs/vb и OrganizationService.metadata.cs/vb.

  8. Откройте файл OrganizationService.cs/vb.

    Обратите внимание, что для каждой сущности созданы методы запроса, вставки, обновления и удаления. Для сущности всегда создается метод запроса. Методы вставки, обновления и удаления были добавлены благодаря выбранному параметру Включить редактирование.

  9. Настройте метод запроса GetEmployees() так, чтобы он возвращал сотрудников, отсортированных по EmployeeID, заменив сформированный код следующим кодом.

    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. Создайте решение.

    При построении решения создаются контекст домена и сущности в клиентском проекте.

  11. Откройте файл EmployeeList.xaml.

  12. Перетащите из области элементов элемент управления DataGrid в представление конструктора сразу после элемента управления TextBlock.

    При перетаскивании элемента DataGrid в представление конструктора добавляется ссылка на сборку System.Windows.Controls.Data, а в элемент Page добавляется префикс sdk.

  13. Измените значения по умолчанию в элементе управления DataGrid, удалив свойства Height и Width, сделав его доступным только для чтения, настроив на автоматическое создание столбцов и установив его минимальную высоту.

    <sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" />
    
  14. Сохраните файл EmployeeList.xaml.

  15. Откройте файл EmployeeList.xaml.cs/vb.

  16. Добавьте следующие инструкции using или Imports.

    Imports System.ServiceModel.DomainServices.Client
    
    using HRApp.Web;
    using System.ServiceModel.DomainServices.Client;
    
  17. Создайте экземпляр класса OrganizationContext и загрузите данные о сотрудниках, добавив следующий код в файл EmployeeList.xaml.cs/vb.

    Класс OrganizationContext автоматически создается в клиентском проекте на основе класса OrganizationService из серверного проекта.

    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. Запустите приложение.

  19. Щелкните ссылку Список сотрудников, чтобы увидеть элемент DataGrid.

    RIA_HRAppDataGrid

Добавление пользовательского запроса

  1. В проекте HRApp.Web откройте файл OrganizationService.cs/vb.

  2. Добавьте новый метод с именем GetSalariedEmployees, добавив следующий код в текст класса.

    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. Создайте решение.

  4. В клиентском проекте откройте файл EmployeeList.xaml.cs/vb.

  5. В конструкторе замените вызов GetEmployeesQuery() вызовом GetSalariedEmployeesQuery().

    _OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery())
    
    _OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery());
    
  6. Запустите приложение и щелкните ссылку Список сотрудников.

    Обратите внимание, что у всех отображаемых сотрудников отмечено значение SalariedFlag. Сотрудники с EmployeeID 1, 2, и 4 больше не отображаются в списке, так как они не являются штатными.

    RIA_HRAppFilteredDataGrid

Добавление источника данных домена

  1. Откройте файл EmployeeList.xaml.

  2. Перетащите из области элементов элемент управления DomainDataSource в представление конструктора непосредственно перед элементом DataGrid. Элемент DomainDataSource может отображаться внизу списка элементов управления.

    TipСовет.
    Если элемент управления DomainDataSource отсутствует в области элементов, щелкните правой кнопкой мыши область элементов и выберите команду Выбрать элементы. На вкладке Компоненты Silverlight отметьте DomainDataSource и нажмите кнопку ОК.

    После перетаскивания элемента управления DomainDataSource в представление конструктора создается ссылка с префиксом riaControls для пространства имен System.Windows.Controls в элементе Page. Кроме того, в левом нижнем углу представления конструктора появляется значок источника данных.

  3. Для решений C# добавьте следующее объявление пространства имен в файл XAML.

    xmlns:ds="clr-namespace:HRApp.Web"
    
  4. Для решений Visual Basic добавьте следующее объявление пространства имен в файл XAML.

    xmlns:ds="clr-namespace:HRApp"
    
  5. Присвойте элементу управления DomainDataSource имя employeeDataSource и задайте LoadSize, AutoLoad и метод запроса, заменив существующий XAML-код следующим XAML-кодом.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
    </riaControls:DomainDataSource>
    
  6. Задайте DomainContext для элемента DomainDataSource, добавив следующий XAML-код.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True">
        <riaControls:DomainDataSource.DomainContext>
            <ds:OrganizationContext/>
        </riaControls:DomainDataSource.DomainContext>
    </riaControls:DomainDataSource>
    
  7. Замените DataGrid следующим XAML-кодом.

    <sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" Height="Auto" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />
    
  8. Откройте файл EmployeeList.xaml.cs/vb.

  9. В конструкторе удалите или закомментируйте код создания экземпляра OrganizationContext, вызов метода GetSalariedEmployeesQuery(), а также код, задающий для элемента управления DataGrid свойство ItemsSource.

    Явная загрузка данных больше не понадобится, так как DomainDataSource сделает это автоматически.

    '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. Запустите приложение и щелкните ссылку Список сотрудников.

    Приложение будет работать так же, как и раньше.

Добавление в источник данных сортировки, фильтрации и разбиения на страницы

  1. Откройте файл EmployeeList.xaml.

  2. В DomainDataSource добавьте следующий элемент SortDescriptors, чтобы указать способ сортировки данных в элементе DataGrid.

    Данный XAML показывает, как сортировать столбец VacationHours в возрастающем порядке.

    <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. Запустите приложение и щелкните ссылку Список сотрудников.

    Данные сортируются по столбцу VacationHours, направление сортировки можно изменить, щелкнув заголовок столбца.

  4. Откройте файл EmployeeList.xaml.

  5. Чтобы разрешить пользователю отфильтровать возвращаемые записи путем указания значения, добавьте следующий XAML-код перед DataGrid.

    Этот XAML-код добавляет элемент управления TextBox, позволяющий пользователю ввести значение.

    <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. В DomainDataSource добавьте дескриптор фильтра, привязанный к элементу управления TextBox, добавленному на предыдущем шаге.

    <riaControls:DomainDataSource.FilterDescriptors>
        <riaControls:FilterDescriptor 
             PropertyPath="VacationHours" 
             Operator="IsGreaterThanOrEqualTo"
             IgnoredValue=""
             Value="{Binding ElementName=vacationHoursText, Path=Text}"  >
        </riaControls:FilterDescriptor>
    </riaControls:DomainDataSource.FilterDescriptors>
    
  7. Запустите приложение и щелкните ссылку Список сотрудников.

  8. В текстовом поле Фильтр мин. кол-ва часов отпуска введите значение 70.

    Обратите внимание, что у перечисленных сотрудников значение VacationHours больше или равно 70.

    RIA_HRAppVacationFilter

  9. Откройте файл EmployeeList.xaml.

  10. Перетащите из области элементов элемент управления DataPager непосредственно под элементом DataGrid.

  11. Задайте размер страницы 5 и установите источник, как показано в следующем XAML-коде.

    <sdk:DataPager PageSize="5" Source="{Binding Data, ElementName=employeeDataSource}" HorizontalAlignment="Left" />
    
  12. Запустите приложение и щелкните ссылку Список сотрудников.

    Вы увидите только 5 строк отфильтрованных данных на страницу, а также элементы управления страничного навигатора под элементом DataGrid.

    RIA_HRAppPagedData

Создание представления «основной/подробности»

В этом разделе используется элемент управления DataForm из набора средств Silverlight для обеспечения детального представления данных. По умолчанию шаблон проекта бизнес-приложения Silverlight содержит двоичный файл System.Windows.Controls.Data.DataForm.Toolkit.dll в папке Libs.

Добавление элемента DataForm

  1. Откройте файл EmployeeList.xaml.

  2. Добавьте следующее объявление пространства имен.

    xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    
  3. После элемента управления DataPager добавьте следующий XAML-код для добавления элемента управления DataForm.

    Этот XAML-код задает атрибуты DataForm и указывает отображаемые столбцы.

    <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. Запустите приложение и щелкните ссылку Список сотрудников.

    В DataForm будут отображены подробности элемента, выбранного в DataGrid.

    RIA_HRAppDataForm

Обновление базы данных

Если установить флажок Включить редактирование в диалоговом окне Новый класс службы домена, на уровне службы домена будут созданы методы для обновления, вставки и удаления сущности. В этом разделе вы добавите кнопки изменения в пользовательский интерфейс списка сотрудников, чтобы пользователи могли выполнять эти операции.

Обновление записи

  1. Откройте файл EmployeeList.xaml.

  2. После элемента управления DataForm добавьте следующий XAML-код для добавления кнопки «Отправить».

    <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. В элементе управления DomainDataSource укажите обработчики событий для события SubmittedChanges.

    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True" SubmittedChanges="employeeDataSource_SubmittedChanges">
    
  4. Откройте файл EmployeeList.xaml.cs/vb.

  5. Добавьте следующие обработчики событий для события нажатия на кнопку.

    Кнопка submitButton будет отключена, чтобы предотвратить повторную отправку пользователем изменения во время обработки операции.

    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. Добавьте обработчики событий для события SubmittedChanges, которое проверит, завершена ли успешно операция отправки, и включит кнопку submitButton.

    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. Запустите приложение и щелкните ссылку Список сотрудников.

  8. Выберите сотрудника и щелкните значок карандаша в верхнем правом углу формы данных, чтобы включить редактирование.

    Теперь можно изменить любое редактируемое поле.

  9. Внесите изменения в данные о сотруднике и нажмите кнопку ОК.

  10. Нажмите кнопку Отправить, чтобы сохранить данные.

    Изменения будут сохранены в базе данных на сервере только после нажатия кнопки «Отправить».

Добавление пользовательских методов к службе домена

  1. В серверном проекте HRApp.Web откройте файл OrganizationService.cs/vb. Файл

  2. Добавьте следующий пользовательский метод с именем ApproveSabbatical.

    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. Создайте решение.

  4. Откройте файл EmployeeList.xaml.

  5. После кнопки «Отправить» добавьте следующий XAML-код для добавления кнопки «Утвердить саббатический отпуск».

    <Button x:Name="approveSabbatical" Width="115" Height="23"  Content="Approve Sabbatical"  Margin="4,0,0,0" Click="approveSabbatical_Click"/>
    
  6. Откройте файл EmployeeList.xaml.cs/vb.

  7. Добавьте следующие обработчики событий для события нажатия кнопки, которое будет вызывать операцию домена ApproveSabbatical.

    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. Запустите приложение и щелкните ссылку Список сотрудников.

  9. Нажмите кнопку Утвердить саббатический отпуск и обратите внимание, что флажок CurrentFlag для выбранного сотрудника снят.

Проверка данных

Элемент DataForm может отображать ошибки проверки с уровня доступа к данным (DAL). Например, если ввести нецелочисленное значение в поле VacationHours, отображается ошибка проверки. На следующем рисунке показан пример поведения при проверке.

RIA_HRAppValidation

Если установить флажок Сформировать связанные классы для метаданных в диалоговом окне Новый класс службы домена, будет создан файл, который содержит метаданные. В данном пошаговом руководстве файл метаданных называется OrganizationService.metadata.cs/vb. В этом разделе вы добавите в этот файл атрибуты проверки. Правила проверки будут принудительно установлены в клиентском и серверном проектах.

Также вы создадите пользовательский интерфейс, позволяющий добавить в базу данных новые записи о сотрудниках. Правила проверки, добавленные в предыдущих разделах, автоматически будут применены в новом пользовательском интерфейсе.

Добавление основной проверки

  1. В проекте HRApp.web откройте файл OrganizationService.metadata.cs/vb.

  2. Добавьте следующие атрибуты к свойствам Gender и VacationHours.

    <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. Создайте решение.

  4. Запустите приложение и щелкните ссылку Список сотрудников.

  5. Выберите сотрудника и щелкните значок карандаша в верхнем правом углу формы данных, чтобы включить редактирование.

  6. Введите значение в поле Часы отпуска, которое не попадает в допустимый диапазон (0–70), и переместите фокус на другой элемент управления.

    Отобразится ошибка проверки часов отпуска.

    RIA_HRAppRangeValidation

  7. Удалите значение из поля Пол и переместите фокус на другой элемент управления.

    Отобразится ошибка проверки пола.

Добавление пользовательской проверки

  1. В Обозревателе решений щелкните правой кнопкой мыши проект HRApp.Web, выберите Добавить, а затем Новый элемент.

    Откроется диалоговое окно Добавление нового элемента.

  2. В категории Код выберите шаблон Файл кода.

  3. Назовите новый элемент OrganizationService.shared.cs или OrganizationService.shared.vb.

    Файлы, имя которых заканчивается на .shared.cs или .shared.vb, доступны как в клиентском, так и в серверном проектах. Общие файлы позволяют выполнять то же правило проверки в обоих проектах. После построения решения на последующем этапе загляните в скрытую папку Generated_Code на клиенте и увидите файл OrganizationService.shared.cs/vb.

  4. Нажмите кнопку Добавить.

  5. Для создания пользовательского класса проверки, который проверяет значения, назначенные свойству Gender, добавьте в общий файл следующий код.

    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. Откройте файл OrganizationService.metadata.cs/vb.

  7. Добавьте следующий пользовательский атрибут проверки к свойству Gender.

    <Required()> _
    <CustomValidation(GetType(GenderValidator), "IsGenderValid")> _
    Public Property Gender As String
    
    [CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")]
    [Required]
    public string Gender { get; set; }
    
  8. Создайте решение.

  9. Запустите приложение и щелкните ссылку Список сотрудников.

  10. Выберите сотрудника и щелкните значок карандаша в верхнем правом углу формы данных, чтобы включить редактирование.

  11. Введите значение в поле Пол, отличное от «М» или «Ж», и переместите фокус на другой элемент управления.

    Появится результат пользовательской проверки.

    RIA_HRAppCustomValidation

Добавление новых записей

В этом разделе вы добавите форму, которая позволит пользователю создать новую запись в таблице Employee.

Добавление новой записи

  1. В проекте HRApp добавьте новый элемент.

  2. В категории Silverlight выберите шаблон Дочернее окно Silverlight.

  3. Назовите новый элемент EmployeeRegistrationWindow.xaml.

    RIA_HRAppAddChildWindow

  4. Нажмите кнопку Добавить.

  5. Откройте файл EmployeeRegistrationWindow.xaml.cs/vb.

  6. В случае использования C# добавьте следующую инструкцию using.

    using HRApp.Web;
    
  7. Добавьте свойство для новой сущности Employee, создаваемой с пользовательскими значениями.

    Public Property NewEmployee As Employee
    
    public Employee NewEmployee { get; set; }
    
  8. Откройте файл EmployeeRegistrationWindow.xaml.

  9. Добавьте следующее объявление пространства имен в файл EmployeeRegistrationWindow.xaml для использования элемента управления DataForm в этом окне.

    xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    
  10. Добавьте следующий элемент управления DataForm в файл EmployeeRegistrationWindow.xaml непосредственно перед кнопкой «Отмена».

    <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. Откройте файл EmployeeRegistrationWindow.xaml.cs/vb.

  12. Добавьте следующий код для создания нового экземпляра Employee и обработки либо фиксации нового экземпляра, либо отмены вставки.

    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. Откройте файл EmployeeList.xaml.

  14. Между DataPager и DataForm добавьте следующий XAML-код, чтобы создать кнопку с именем addNewEmployee.

    <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. Откройте файл EmployeeList.xaml.cs/vb.

  16. Добавьте следующий код для обработки события нажатия кнопки и отображения окна EmployeeRegistrationWindow.

    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. Добавьте следующий метод для обработки события closed окна EmployeeRegistrationWindow.

    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. Откройте файл OrganizationService.cs/vb.

  19. Измените метод InsertEmployee, добавив следующий код.

    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. Запустите приложение и щелкните ссылку Список сотрудников.

  21. Нажмите кнопку Добавить сотрудника.

    Откроется окно EmployeeRegistrationWindow.

    RIA_Employee_Registration

  22. Добавьте данные в окне и установите флажок Служащий.

  23. Нажмите кнопку ОК.

  24. Обновите страницу и убедитесь, что новый сотрудник отображается в DataGrid.

Проверка подлинности пользователей

В этом разделе вы ограничите доступ к методу ApproveSabbatical только пользователями, прошедшими проверку подлинности.

Добавление проверки подлинности

  1. Откройте файл OrganizationService.cs/vb.

  2. Добавьте атрибут RequiresAuthentication к методу ApproveSabbatical.

    Применение атрибута RequiresAuthentication к операции домена позволяет обеспечить, чтобы операцию могли вызвать только пользователи, прошедшие проверку подлинности. Если анонимный пользователь нажмет кнопку Утвердить саббатический отпуск, операция не будет выполнена.

    <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. Откройте файл EmployeeList.xaml.cs/vb.

  4. Добавьте следующие инструкции using или Imports.

    Imports System.ServiceModel.DomainServices.Client.ApplicationServices
    Imports HRApp.LoginUI
    
    using System.ServiceModel.DomainServices.Client.ApplicationServices;
    using HRApp.LoginUI;
    
  5. Измените метод approveSabbatical_Click и добавьте обработчик LoggedIn, который будет проверять, прошел ли пользователь проверку подлинности.

    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. Запустите приложение и щелкните ссылку Список сотрудников.

  7. Выберите запись сотрудника и нажмите кнопку Утвердить саббатический отпуск.

    Вы будете перенаправлены в окно входа.

  8. Щелкните ссылку Зарегистрируйтесь сейчас.

  9. Заполните обязательные поля для создания новой учетной записи.

  10. Нажмите кнопку ОК.

    Вы выполнили вход с использованием соответствующей учетной записи, и ваше имя отображается на панели под навигационными ссылками.

Отображение связанных данных

С помощью Службы RIA можно легко работать с данными из связанных таблиц. В этом разделе вы добавите новую страницу Silverlight и отобразите данные из таблиц PurchaseOrderHeader и PurchaseOrderDetail. Также можно настроить операции изменения данных, чтобы взаимосвязанные данные изменялись вместе. Пример изменения данных в взаимосвязанных таблицах посредством операции домена см. в разделе Композиционные иерархии.

Отображение данных из взаимосвязанных таблиц

  1. В проекте HRApp щелкните правой кнопкой мыши папку Views, выберите Добавить, а затем Новый элемент.

  2. Добавьте новую страницу Silverlight с именем PurchaseOrders.xaml.

  3. Откройте файл PurchaseOrders.xaml.

  4. Добавьте следующий XAML-код между тегами <Grid>.

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource 
      PageScrollViewerStyle}" >
        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
    
            <TextBlock Text="Purchase Orders" Style="{StaticResource HeaderTextStyle}"/>
        </StackPanel>
    </ScrollViewer>
    
  5. Откройте файл MainPage.xaml.

  6. После ссылки EmployeeList добавьте следующий XAML-код, чтобы включить ссылку на страницу PurchaseOrders.

    <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>
    
    <HyperlinkButton x:Name="Link4" Style="{StaticResource LinkStyle}" NavigateUri="/PurchaseOrders" TargetName="ContentFrame" Content="Purchase Orders"/>
    
  7. Откройте файл OrganizationService.metadata.cs/vb.

  8. Добавьте атрибуты Include и Composition к свойству PurchaseOrderDetails в классе PurchaseOrderHeaderMetadata.

    <Include()> _
    <Composition()> _
    Public Property PurchaseOrderDetails As EntityCollection(Of PurchaseOrderDetail)
    
    [Include]
    [Composition]
    public EntityCollection<PurchaseOrderDetail> PurchaseOrderDetails { get; set; }
    
  9. Откройте файл OrganizationService.cs/vb.

  10. Измените метод GetPurchaseOrderHeaders так, чтобы связанные записи из PurchaseOrderDetails также извлекались этим запросом.

    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. Откройте файл PurchaseOrders.xaml.

  12. Чтобы открыть окно Источники данных, щелкните пункт Показать источники данных в меню Данные.

  13. Перетащите узел PurchaseOrderHeader в область конструктора для файла PurchaseOrders.xaml.

    RIA_Order_Header

    Будет отображен элемент DataGrid со столбцами из таблицы PurchaseOrderHeader.

  14. В окне Источники данных раскройте узел PurchaseOrderHeader.

  15. Перетащите узел PurchaseOrderDetails, который расположен в узле PurchaseOrderHeader, в область конструктора непосредственно под DataGrid для PurchaseOrderHeader.

    RIA_Order_Details

    Будет отображен элемент DataGrid со столбцами из таблицы PurchaseOrderDetails.

  16. В представлении XAML найдите элементы управления DataGrid как для PurchaseOrderHeader, так и для PurchaseOrderDetails.

  17. Удалите свойство Width=”400” из каждого элемента DataGrid таким образом, чтобы он заполнил доступную ширину.

  18. Перед элементом DataGrid с содержимым PurchaseOrderHeader добавьте следующий элемент управления TextBlock для снабжения данных подписью.

    <TextBlock Text="Order Headers"></TextBlock>
    
  19. Перед элементом DataGrid с содержимым PurchaseOrderDetails добавьте следующий элемент управления TextBlock для снабжения данных подписью.

    <TextBlock Text="Order Details"></TextBlock>
    
  20. Чтобы ограничить количество извлекаемых записей, добавьте следующий дескриптор фильтра к элементу управления DomainDataSource.

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

    Ниже приведен полный XAML-код для файла PurchaseOrders.xaml.

    <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. Запустите приложение и щелкните ссылку Заказы на покупку.

  22. Выберите другие записи в элементе DataGrid с содержимым PurchaseOrderHeader.

    Обратите внимание, что автоматически отображаются связанные записи из PurchaseOrderDetail.

    RIA_Details_and_Header

Следующие шаги

Данное пошаговое руководство предоставило обзор многих функций Службы RIA . Для изучения подробных сведений о конкретных областях см. другие пошаговые руководства в данной документации.

См. также

Задачи

Пошаговое руководство. Ввод данных в бизнес-приложении Silverlight
Пошаговое руководство. Использование службы проверки подлинности с бизнес-приложением Silverlight