Спонсор: Microsoft
Опубликован: 13.12.2011 | Доступ: свободный | Студентов: 982 / 29 | Оценка: 4.29 / 4.57 | Длительность: 13:56:00
Лекция 5:

Silverlight и WPF в Visual Studio 2010 (продолжение)

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >

Улучшенная поддержка шаблона MVVM

Данная поддержка состоит в расширении перечислимого типа UpdateSourceTrigger значением PropertyChanged. Данное значение влияет на обновление источника данных, происходящее при обновлении цели (элемента, куда данные выгружаются). Ранее этот тип поддерживал лишь два значения, это LostFocus и Explicit. Иными словами, если Вы связываете данные с элементом управления TextBox, то в случае двунаправленного связывания, при изменении элемента TextBox, источник мог быть обновлен лишь при потере фокуса или явным образом. Значение PropertyChanged позволяет реагировать на любые изменения в текстовом поле "на лету". При этом нет необходимости обрабатывать нажатия клавиш и т .д. Вот пример кода:

   1:  <UserControl x:Class="SilverlightApplication1.MainPage"
   2:      xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
   3:      xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
   4:      xmlns:d=http://schemas.microsoft.com/expression/blend/2008
   5:      xmlns:mc=http://schemas.openxmlformats.org/markup-ompatibility/2006
   6:      Loaded="UserControl_Loaded"
   7:      mc:Ignorable="d"
   8:      d:DesignHeight="300" d:DesignWidth="400">
   9:   
  10:      <Grid x:Name="LayoutRoot" Background="White">
  11:          <Grid.Resources>
  12:              <Style TargetType="TextBox">
  13:                  <Setter Property="Background" Value="AliceBlue"/>
  14:                  <Setter Property="Width" Value="200"/>
  15:                  <Setter Property="Margin" Value="5"/>
  16:              </Style>
  17:              <Style TargetType="TextBlock">
  18:                  <Setter Property="Margin" Value="5"/>
  19:              </Style>
  20:          </Grid.Resources>
  21:          <Grid.RowDefinitions>
  22:              <RowDefinition Height="Auto"></RowDefinition>
  23:              <RowDefinition Height="Auto"></RowDefinition>
  24:          </Grid.RowDefinitions>
  25:          <Grid.ColumnDefinitions>
  26:              <ColumnDefinition Width="Auto"></ColumnDefinition>
  27:              <ColumnDefinition Width="Auto"></ColumnDefinition>
  28:          </Grid.ColumnDefinitions>
  29:   
  30:          <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0"/>
  31:          <TextBox Grid.Row="0" Grid.Column="1" Text=
  32:            "{Binding FirstName, UpdateSourceTrigger=PropertyChanged, 
                    Mode=TwoWay}">
  33:          </TextBox>
  34:          <TextBlock Text="Your First Name:" Grid.Column="0"         
                     Grid.Row="1"/>
  35:          <TextBlock Text="{Binding FirstName}" Grid.Column="1" 
                     Grid.Row="1"/ >
  36:   
  37:      </Grid>
  38:  </UserControl>

Ну и код модифицированного класса (чтобы работало связывание в двух направлениях):

   1:  public class Person: INotifyPropertyChanged 
   2:  {
   3:      public string firstName;
   4:   
   5:      public string FirstName {
   6:          get { return firstName; }
   7:          set { 
   8:              firstName = value;
   9:              OnPropertyChanged(new
                       PropertyChangedEventArgs("FirstName"));
  10:          } 
  11:      }
  12:   
  13:      public event PropertyChangedEventHandler PropertyChanged;
  14:   
  15:      public void OnPropertyChanged(PropertyChangedEventArgs e)
  16:      {
  17:          if (PropertyChanged != null)
  18:              PropertyChanged(this, e);
  19:      }
  20:   
  21:  }

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

Использование связывания в стилях

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

   1:  <Grid.Resources >
   2:      <Style TargetType="TextBox">
   3:          <Setter Property="Background" Value="{Binding background}"/>
   4:          <Setter Property="Width" Value="{Binding width}"></Setter>
   5:          <Setter Property="Margin" Value="{Binding margin}"></Setter>
   6:      </Style>
   7:      <Style TargetType="TextBlock">
   8:          <Setter Property="Margin" Value="{Binding margin}"></Setter>
   9:      </Style>
  10:  </Grid.Resources>

Класс модели

   1:  public class TextStyle
   2:  {
   3:      public string width { get; set; }
   4:      public string background { get; set; }
   5:      public string margin { get; set; }
   6:  }

И связывание:

   1:  LayoutRoot.DataContext = new TextStyle() 
   2:  { width = "200", background = "Blue", margin = "5" };

Неявные шаблоны

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

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

Создадим проект и добавим несколько типов данных

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Title { get; set; }
    public string Company { get; set; }
}

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Room { get; set; }
}

Добавим несколько шаблонов данных в ресурсы приложения(файл App.xaml)

<Application
     xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     x:Class="ImplicitDataTemplate.App"
     xmlns:data="clr-namespace:ImplicitDataTemplate">
    <Application.Resources>
        <DataTemplate DataType="data:Customer">
            <Grid Background="LightSkyBlue">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                Grid.RowDefinitions>
                <StackPanel Orientation="Horizontal">
                   <TextBlock Text="{Binding FirstName, 
                                        StringFormat='\{0\} '}"/>
                   <TextBlock Text="{Binding LastName}"/>
                </StackPanel>
                <StackPanel Grid.Row="1">
                    <TextBlock Text="{Binding Title}" FontStyle="Italic"/>
                    <TextBlock Text="{Binding Company, 
                        StringFormat='Компания: \{0\}'}" FontWeight="Bold"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <DataTemplate DataType="data:Employee">
            <Grid Background="LightGreen" >
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                 <Grid.RowDefinitions>
                <StackPanel Orientation="Horizontal" 
                            HorizontalAlignment="Right">
                    <TextBlock Text="{Binding FirstName,
                                         StringFormat='\{0\} '}"/>
                    <TextBlock Text="{Binding LastName}"/>
                </StackPanel>
                <StackPanel Grid.Row="1" Orientation="Horizontal" 
                                         HorizontalAlignment="Right">
                    <TextBlock Text="{Binding Room,
                        StringFormat='Комната: \{0\}'}" FontStyle="Italic"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Application.Resources>
</Application>

И последний момент, создание тестовых данных в приложении, связывание их с формой

this.DataContext = new List<object>
{
  new Customer{ FirstName="Иван", LastName="Копаткинский", 
                   Company="Топинамбур", Title="Бухгалтер"},
  new Customer{ FirstName="Дмитрий", LastName="Вирутон",
                   Company="Пальма туриста", Title="Менеджер"},
  new Employee{ FirstName="Павел", LastName="Уловинко", Room=101}
};

и добавление компонента ListBox для отображения списка данных

<Grid x:Name="LayoutRoot" Background="White">
        <ListBox ItemsSource="{Binding}"/>
</Grid>

Результат работы:

Результат применения неявных шаблонов в Silverlight 5

Рис. 7.8. Результат применения неявных шаблонов в Silverlight 5

Другие изменения

Для полноты статьи приведем еще несколько нововведений, которые сами по себе интересны, но не стоят отдельного раздела из-за своей прозрачности (понятности).

Особое внимание стоит обратить на новое событие DataContextChanged, которое представлено в базовом классе FrameworkElement. Теперь элемент способен отреагировать на изменение источника данных.

Если связывание происходит с другими элементами в модели, то теперь можно использовать свойство RelativeSource совместно с FindAncestor. Это позволяет указать вместо имени элемента, его тип и уровень вложенности. В результате нужный элемент будет найден в реальном времени и выполнено связывание.

Последнее нововведение, это доступность интерфейса ICustomTypeProvider, описывающего метод GetCustomType. Данный интерфейс может быть полезен, когда Вы создаете объекты с динамически сгенерированными свойствами. В этом случае Вы генерируете и возвращаете объект типа Type, описывающий все свойства, которые Вы хотели бы использовать при связывании. Аналогичным образом можно поступить, когда Вы хотите скрыть некоторые свойства от элементов управления, генерирующих свою структуру автоматически. Например, DataGrid, генерирующий свои колонки автоматически.

Краткие итоги

Silverlight – новая технология от Mirosoft, предназначенная для разработки насыщенных Web – приложений. Особенности версии Silverlight 4 – интенсивное использование графики, анимации, работа с медиа-файлами, а так же эффективное взаимодействие с данными и серверными компонентами. В декабре 2010 года в Microsoft сообщили, что Silverlight 5 будет включать 40 новых функций. Большая часть которых, также как и в изменениях, пришедших с 4 версией Silverlight, сосредоточена вокруг графики, анимации и работы с медиа-файлами. 1 сентября 2011 Silverlight 5 от Microsoft перешел в стадию Release Candidate. Выход финальной версии технологии по-прежнему намечен на конец 2011 года.

Набор для практики

Вопросы:

  1. Назовите ключевые особенности Silverlight 4
  2. Охарактеризуйте основные нововведения Silverlight 5, связанные с текстом
  3. Повышение полномочий для приложений в браузере
  4. Поддержка нескольких окон в Silverlight 5
< Лекция 4 || Лекция 5: 1234 || Лекция 6 >
Игорь Ключников
Игорь Ключников
Россия
Михаил Ковязо
Михаил Ковязо
Россия, Москва, ВЗМИ, 1982