Опубликован: 13.12.2011 | Уровень: для всех | Доступ: платный
Лекция 5:

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

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

Поддержка нескольких окон

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

Ниже приведен небольшой код, который, внутри конструктора главного окна, генерирует дочернее окно и делает его видимым:

  public MainPage()
  {
  InitializeComponent();
   
     Window childWindow = new Window();
     childWindow.Height = 400;
     childWindow.Width = 600;
     childWindow.Top = 30;
     childWindow.Left = 30;
     childWindow.Title = "Child Window";
     childWindow.Visibility = Visibility.Visible;
  }

В данном примере дочернее окно создается с размерами 600 на 400, при этом верхний левый его угол будет находиться в позиции (30, 30), относительно экрана системы (не родительского окна). При этом обратите внимание на то, что созданное окно поддерживается панелью задач Windows 7 (рис. 7.4):

Поддержка нескольких окон в Silverlight 5

Рис. 7.4. Поддержка нескольких окон в Silverlight 5

Доступ к файловой системе для приложений с повышенными привилегиями

Технология Silverlight 4 поддерживала возможность приложениям с повышенными привилегиями получать доступ к файловой системе пользователя. Правда, доступ был ограничен лишь несколькими папками. Так, в режиме с повышенными привилегиями, приложения получают полный контроль к специальным папкам, ассоциированным с пользователем: MyDocuments, MyVideos, MyPictures, MyMusic. Пути к указанным папкам можно получить, используя статический класс Environment. При этом нужно отметить, что SilverLight-приложение работает только с папками, но не с библиотеками (Windows 7).

В Silverlight 5 появилась возможность взаимодействовать со всей файловой системой пользователя. Речь идет как о чтении файлов, так и о записи.

Установка имени файла по умолчанию в SaveFileDialog

Теперь при вызове этого диалогового окна, можно установить имя файла (как и список расширений), которое будет отображаться по умолчанию, как имя файла, предлагаемого для записи. Вот как это выглядит:

SaveFileDialog dialog = new SaveFileDialog();
dialog.DefaultFileName = "hello.txt";
dialog.ShowDialog();

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

Улучшение работы с аудио

В Silverlight 5 стала доступна библиотека по работе с Media. Классы этой библиотеки представлены пространством имен Microsoft.Xna.Framework.Audio. Нетрудно догадаться, что данный шаг выполнен в рамках интеграции с XNA библиотеками, которые можно использовать и в Silverlight (это аудио и 3D).

Новое пространство имен содержит два основных класса, позволяющих создавать аудио эффекты в процессе работы Silverlight приложения. Файлы, доступные для проигрывания, должны быть в формате WAV и могут быть загружены с помощью класса SoundEffect. Конструктор этого класса получает ссылку на набор данных и (или) настройки аудио. Создание конкретного экземпляра можно также выполнить с помощью статического метода FromStream, получающего ссылку на поток в качестве параметров. Проигрывание эффекта осуществляется с помощью метода Play. Каких-то других методов SoundEffect не имеет, но это вовсе не означает, что отдельно взятым объектом нельзя управлять. Так, если вы хотите не просто воспроизвести эффект, но и добавить элементы управления аудио (громкость, пауза и т .д.), то вместо метода Play следует вызывать метод CreateInstance, создающий конкретный экземпляр на базе SoundEffect, и возвращающий ссылку типа SoundEffectInstance, которая позволит управлять нашим аудио файлом.

SoundEffect sEffect=SoundEffect.FromStream(streamInfo.Stream);
sEffect.Play();

Изменение скорости проигрывания медиа

В Silverlight 5 произошли улучшения и в MediaElement элементе. Теперь этот элемент управления содержит такое свойство как PlaybackRate и событие RateChanged. Свойство позволяет задавать скорость проигрывания, синхронизировать видео и звук, а также выполнять "переметку" не только вперед, но и назад. Предполагается, что можно будет использовать следующие множители для скорости проигрывания: 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 8, 16, 32. Событие RateChanged позволит реагировать на изменение свойства.

Поддержка пульта дистанционного управления

Silverlight 5 поддерживает и работу с пультом. Данная функциональность стала доступна благодаря поддержке события MediaCommand, которое доступно у всех UIElement. Иными словами, если вы хотите обрабатывать нажатия кнопок пульта, то Вам следует обработать это событие у родительского контейнера (от дочерних элементов оно как раз туда и свалится). Чтобы понять, какая кнопка на пульте была нажата, обработчик события получает доступ к свойству в MediaCommandEventArgs, содержащему свойство перечислимого типа MediaCommand. Последнее и содержит информацию по нажатой кнопке.

Работа с текстом

Silverlight 5 предлагает несколько интересных возможностей при работе с текстом. Так, элементы управления Control, TextBlock и TextElement, имеют новое свойство CharacterSpacing. Это свойство позволяет установить расстояние между символами внутри текста.

Свойство LineHeight позволяет установить ширину строки (можно интерпретировать, как расстояние между строками) и определено в таких элементах как Block, TextBlock, TextBox и RichTextBox. Для элемента RichTextBox можно также задать стратегию с помощью свойства LineStackingStrategy. На рис. 7.5 пример текста внутри элемента TextBlock с расстоянием между строками 30 и расстоянием между символами – 200:

Пример возможности TextBlock в Silverlight 5

Рис. 7.5. Пример возможности TextBlock в Silverlight 5

Наконец, Silverlight 5 стал поддерживать два новых текстовых элемента, это RichTextBlock и RichTextBlockOverflow. Эти элементы аналогичны элементам RichTextBox и RichTextBoxOverflow, но позволяют отображать текст только на чтение.

Рассмотрим небольшой пример с элементом RichTextBlockOverflow:

  <StackPanel x:Name="LayoutRoot" Background="White"
     Orientation="Horizontal" VerticalAlignment="Top">
     <RichTextBlock
        Width="250" FontSize="16" OverflowContentTarget=
        "{Binding ElementName=SecondBox}">
        <Paragraph>
           В лесу родилась елочка,
        </Paragraph>
        . . . . . . . . //повторить 20 разJ
     </RichTextBlock>
   
     <RichTextBlockOverflow Width="250" Name="SecondBox">
     </RichTextBlockOverflow>
  </StackPanel>

Результат работы этого кода показан на рис. 7.6:

Пример с элементом RichTextBlockOverflow в Silverlight 5

Рис. 7.6. Пример с элементом RichTextBlockOverflow в Silverlight 5

Как видно, RichTextBlockOverflow может отображать текст, который не "вмещается" в основной элемент RichTextBlock. Благодаря таким элементам мы можем размещать текст в 2, 3 и более колонках (или реализовывать более сложные сценарии).

Печать

Silverlight 5 позволяет теперь не только реализовать растровую, но и векторную печать. Для этих целей используется все тот же метод Print класса PrintDocument, который осуществляет попытку печати в векторном формате, а в случае неудачи (принтер не поддерживает), перейти к печати в растровом виде. Растровую печать можно инициировать с помощью нового метода PrintBitmap.

P/Invoke

В документации эта возможность пока не описана, но она уже реализована – возможность вызова методов Windows API из Silverlight приложений, обладающих повышенными полномочиями. Причем речь идет о приложениях, которые работают как в браузере, так и вне браузера. Поскольку вызов нативных функций в .NET обычно осуществляется с помощью атрибута DllImport. Запустим приложение с повышенными привилегиями:

  public partial class MainPage : UserControl
  {
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, 
      String text, String caption, uint type);
   
    public MainPage()
    {
     MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
     InitializeComponent();
    }
  }

На экране поверх браузера вы увидите стандартный MessageBox.

Отладка при связывании с данными

Современный отладчик в Visual Studio давно позволяет разработчику получать всю необходимую информацию, если речь идет о коде на C#, C++ или даже JavaScript. Но как только речь заходит о XAML, то тут механизмы отсутствуют. Казалось бы, зачем нужна отладка в XAML, если тут идет декларативное описание интерфейса приложения. Действительно, отладка в XAML не нужна, если речь не идет о связывании с данными. Небольшой кусок кода, связывающий наши данные и интерфейс, может вызвать массу проблем при отладке. Ведь причин для возникновения проблем при связывании может быть множество, это и отсутствие какого-либо свойства, и проблемы с преобразованием либо же несоответствие типа. Но если связывание с данными описывается в XAML, то механизма получить информацию о проблеме не было. В Silverlight 5 возможна отладка XAML кода, описывающего связывание элементов управления и данных.

Рассмотрим небольшой пример кода на XAML:

  <UserControl x:Class="SilverlightApplication1.MainPage"
      xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
      xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
      xmlns:d=http://schemas.microsoft.com/expression/blend/2008
      xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006
      Loaded="UserControl_Loaded"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">

      <Grid x:Name="LayoutRoot" Background="White">
          <Grid.Resources>
              <Style TargetType="TextBox">
                  <Setter Property="Background" Value="AliceBlue"></Setter>
                  <Setter Property="Width" Value="200"></Setter>
                  <Setter Property="Margin" Value="5"></Setter>
              </Style>
              <Style TargetType="TextBlock">
                  <Setter Property="Margin" Value="5"></Setter>
              </Style>
          </Grid.Resources>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto"></RowDefinition>
              <RowDefinition Height="Auto"></RowDefinition>
              <RowDefinition Height="Auto"></RowDefinition>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto"></ColumnDefinition>
              <ColumnDefinition Width="Auto"></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0"/> 
          <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="1"/>
          <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="2"/>
          <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FisrtName}"/>
          <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding LastName}"/>
          <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age}"/>
      </Grid>
  </UserControl>

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

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    Person p = new Person();
    p.FirstName = "Sergey";
    p.LastName="Baydachnyy";
    p.Age = 33;
    LayoutRoot.DataContext = p;
}

И класс Person:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

Запустив это приложение, можно убедиться, что первое поле не было заполнено данными. Чтобы понять причину ошибки, достаточно установить Breakpoint в XAML файле на строку, описывающую связывание в первом поле, и запустить приложение в режиме отладки. Вот что можно увидеть в окне Locals:

Отладка XAML в Silverlight 5

увеличить изображение
Рис. 7.7. Отладка XAML в Silverlight 5

Тут и информация об ошибке (ошибка намеренно сделана в имени поля) и данные об объекте и т. д. То есть, сгенерированный объект BindingState четко позволяет выявить проблему и проверить правильность данных.

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >
Анисимов Михаил
Анисимов Михаил
Украина
Наталия Шаститко
Наталия Шаститко
Украина, Днепропетровск, Днепропетровский Гуманитарный Университет, 2014