Silverlight 3: глубокий взгляд изнутри
Аннотация
В данной статье поговорим о новых возможностях технологии Silverlight 3.
Содержание
Что нового
3D проекции
Offline работа
Обновление приложения в разъединенном окружении
Реакция на изменение сетевого интерфейса
SaveFileDialog
Поддержка ToolTip
CaretBrush
Множественный выбор в ListBox
Проверка данных при связывании
Новые элементы управления
Элемент ChildWindow
Элемент Expander, HeaderedContentControl, HeaderedItemsControl
Элемент TreeView
Элемент AutoCompleteBox
Элемент Label
GPU Acceleration
RenderForAnimation
Smooth Streaming
Работа с эффектами
Простая анимация
Улучшенная работа с изображениями, системные цвета
Поддержка системных цветов
Улучшенная работа с кешем
ImageOpened, MediaOpened
Pixel API
Local Connection
Что нового в Silverlight 3
3D проекцииЕстественно, что реализовать механизм полноценного 3D движка в плагине размером 4-6 Мб достаточно тяжело. Между тем псевдо 3D позволяет реализовать множество различных сценариев, но требует от разработчика значительное количество усилий. Благодаря элементу PlaneProjection в SilverLight 3 разработчик может стоить простые проекции, указав всего несколько параметров. Рассмотрим простой код, отображающий MediaElement:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
В результате мы получим MediaElement "повернутый" на 60 градусов по оси Y.
Тут мы использовали элемент PlaneProjection с атрибутом RotationY. Логично, что если Вы хотите развернуть изображение по другим осям, то нужно воспользоваться атрибутами (свойствами) RotationX, RotationZ. Элемент PlaneProjection можно использовать по отношению к любому из элементов-наследников от UIElement.
Добавим к нашему коду 4 слайдера, чтобы изменять угол вращения по запросу пользователя:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
В этом примере мы воспользовались еще одним свойством LocalOffsetZ. Свойства LocalOffsetX, LocalOffsetY, LocalOffsetZ позволяют разместить объект в трехмерном пространстве. Как пример использования этих свойств можно рассмотреть "карусель", где все объекты кроме одного расположны на некотором удалении. Кроме этих свойств существуют еще свойства GlobalOffsetX, GlobalOffsetY, GlobalOffsetZ. Разница между ними только в том, что первые устанавливают смещение относительно текущего контейнера, а вторые - относительно всего окна.
Последние свойства, которые могут быть интересны разработчику, это CenterOfRotationX, CenterOfRotationY, CenterOfRotationZ. Позволяют задать точку, вокруг которой проводить вращение.
О! Мы тронулись и ко мне в шкафчик пришел какой-то бородатый мужик. Мужик - не девушка, поэтому я еще смогу не отвлекаться. Кроме того, он говорит только по английски. Сделаю вид, что я не есть понимать.
Offline работаСледующая интересная возможность - установка SilverLight приложения в локальный кэш пользователя с возможностью запуска в режиме, отключенном от сети.
Для того, чтобы установить приложение в кэш на машине пользователя, необходимо выполнить два шага:
1). Вызвать метод Detach у объекта Application. При этом данный метод должен быть вызван только из обработчика события, инициируемого пользователем. Например, событие может быть связано с нажатием на кнопку.
Добавим кнопку в предыдущий XAML файл.
Разместите кнопку сразу после последнего элемента Slider.
Обработчик нажатия на кнопку будет выглядеть так:
private void Button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Detach();
}
2). Добавить несколько элементов в манифест приложения. Эти элементы необходимы в первую очередь для того, чтобы предоставить дополнительные параметры, которые нужны при развертывании приложения на клиент (надписи, иконки). Вот как будет выглядеть наш манифест:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
Title="My Title">
This is my offline App
Если Вы хотите также описать и иконки, то добавьте следующий элемент:
Если иконки явно не указаны, то подставляется иконка по умолчанию.
Теперь можно запустить приложение и нажать на кнопку. На экране появится следующее сообщение:
Итак, пользователь выбирает, где он хочет видеть иконку своего приложения и должен нажать ОК для установки приложения в кэш. Нужн отметить, что для установки приложения в кэш пользователь НЕ должен обладать административными правами.
Для удаления приложения пользователь должен инициировать вызов контекстного меню (раньше можно было вызвать только SilverLight Configuration) и выбрать Remove This Application. При этом команда доступна вне зависимости от того запустил пользователь локальную версию или воспользовался браузером.
Работая с приложение в отключенном режиме программист имеет возможность определять метод запуска приложения, а также реагировать на изменение метода запуска. Во-первых в объекте Application всегда доступно свойство ExecutionState, через которое можно получить значение перечислимого типа ExecutionStates. Последнее может содержать следующие значения: Detached, DetachedUpdatesAvailable, DetachedFailed, Detaching, RunningOnline. Во-вторых, есть возможность реагировать на событие приложения Application_ExecutionStateChanged.
Работая в отключенном режиме, разработчик может определить состояние подключения. Это может быть очень полезно при реализации механизма синхронизации данных. Проверить соединение можно с помощью вот этого статического метода: NetworkInterface.GetIsNetworkAvailable(). Обращаю Ваше внимание на то, что класс NetworkInterface находится в пространстве имен System.Net.NetworkInformation.
Обновление приложения в разъединенном окруженииЧто же происходит, если приложение было обновлено в сети? Оказывается приложение автоматически проверяет, доступны ли обновления. Это происходит сразу после того, как приложение обнаружило доступ в сеть. Если обновления обнаружены, то они тут же начинают загружаться в кэш пользователя, после чего происходит событие ExecutionStateChanged. Обработав это событие, можно нотифицировать пользователя о том, что обновление уже доступно и ему нужно перезапустить приложение. Какой-либо возможности управлять загрузкой обновлений или отключить эту функциональность (ключи в реестре не считаются) - нет.
Реакция на изменение сетевого интерфейсаОказывается, что оперативно определять разрыв связи с сетью можно с помощью реакции на статическое событие NetworkAddressChanged, которое описано в классе NetworkChange. Это событие происходит всякий раз, когда с сетевым интерфейсом что-то происходит. Далее задача программиста воспользоваться методом GetIsNetworkAvailable, чтобы понять, есть ли соединение.
SaveFileDialogВ предыдущих версиях SilverLight Вы могли общаться с файловой системой только через OpenFileDialog. Это вызывало много нареканий от разработчиков, так как при отображении текстовой информации пользователь не имел возможности сохранить ее на локальный диск. Это же касалось различных графических редакторов и т. д. Теперь разработчик имеет возможность записать на диск любую информацию и в любое место, используя возможности SaveFileDialog. Смотрим пример:
SaveFileDialog file= new SaveFileDialog();
file.Filter = "Text File | *.txt";
file.DefaultExt = ".txt";
file.ShowDialog();
if (file.File.Name != "")
{
System.IO.StreamWriter s =
new System.IO.StreamWriter(file.OpenFile());
s.Write("Hello");
s.Close();
}
Этот код можно разместить в любом методе интерфейсного потока. В результате работы кода, пользователю будет предложено выбрать папку для записи и имя файла (по умолчанию .txt). В файл будет записано Hello. Ничего сложного.
Поддержка ToolTipСледующий интересный элемент управления, это ToolTip. Он может быть привязан к любому UIElement и содержать практически любой контент для отображения. Привязку к элементу можно выполнять, как указав свойство PlacementTarget, так и использовав этот элемент в качестве части контента. Ниже показан код, который позволяет отобразить ToolTip для кнопки. В качестве контента тут используется видео-файл:
ToolTip может быть привязан к одной из границ элемента или к координатам курсора мыши. Привязка задается с помощью свойства Placement.
CaretBrushЕще одной небольшой особенностью SilverLight 3 является возможность установки каретки для текстового поля и поля для задания пароля (TextBox PasswordBox). Дело в том, что элементы в SilverLight реализуются таким образом, что представление отделено от логики. Поэтому разработчик может всегда заменить внешний вид уже существующего элемента. Например, можно создать треугольную кнопку или овальное поле для ввода данных. Но в элементах TextBox и PasswordBox одна часть не поддавалась изменениям - каретка. Она была исключительно черной. Даже, если разработчик просто меня цвет поля ввода, каретку не всегда было видно. Теперь ситуация изменилась. Теперь каретка может использовать любую из доступных кистей для заливки. Разработчик может просто поменять цвет, а может и установить видеоролик в качестве каретки. Вот пример использования свойства:
Поскольку как-то так получилось, что мы начали вести речь об элементах управления, рассмотрим еще один, уже знакомый элемент - ListBox. Тут появилось свойство SelectionMode. Это свойство может содержать одно из трех значений: Single, Multiple, Extended. При установке свойства Multiple пользователь может выбирать несколько значений, простым кликом, а при выборе Extended также доступны функциональные клавиши и поведение больше похоже на полюбившийся ListBox из Forms или WPF.
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
textBox1.Text = String.Format("{0} items selected",listBox1.SelectedItems.Count);
}
Рассмотрим небольшой пример. Для этого опишем простой класс Employee с двумя полями:
public class Employee
{
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
if (!value.Equals("Sergey"))
{
throw new Exception("First Name must be Sergey!");
}
firstName = value;
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public Employee(string fName, string lName)
{
this.FirstName = fName;
this.LastName = lName;
}
}
А также опишем форму, которая связана с объектом типа Employee
И код:
Employee emp;
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
emp = new Employee("Sergey","B");
LayoutRoot.DataContext = emp;
}
Как видно из реализации класса Employee, в качестве имени может быть установленно только Sergey. В SilverLight 3 есть два хороших механизма по обработке ошибок при связывании с данными.
Первый механизм, это специальный элемент управления, который будет нотифицировать пользователя об ошибке связывания. Для этого внесем небольшие изменения в описание TextBox.
Мы добавили простое свойство ValidatesOnException. Чтобы посмотреть на его работу, запустите приложение и введите неверные данные. Поле ввода будет выделено красной рамкой, а при наведении фокуса Вы увидете сообщение, которое заключено в исключении.
Второй механизм позволяет написать код в ответ на исключение при связывании. Для этого изменим TextBox следующим образом:
Тут мы описали обработчик специального события BindingValidationError, а также указали свойство NotifyOnValidationError, которое говорит о необходимости генерации этого события.
А вот и код обработчика:
private void TextBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
textBox1.Focus();
}
Тут мы просто устанавливаем фокус на наше поле, чтобы дополнительно пивлечь внимание пользователя и заставить его исправить ошибку.
Новые элементы управления
Рассматривая существующие элементы управления можно выделить несколько отдельных групп:
- элементы управления, которые входят в стандартную поставку плагина – тут практически ничего не изменилось. О небольших изменениях для ListBox, тултипах, SaveFileDialog и валидаторе я писал ранее. С одной стороны в плагине есть все необходимое, а с другой – увеличение количества элементов привело бы к росту размера плагина;
- элементы, которые входят в SDK – тут присутствует около двух десятков элементов управления, расширяющих существующую иерархию такими элементами, как DataGrid, Calendar и др. Если Вы используете эти элементы, то вместе со своим приложением необходимо поставлять сборку, в которой они расположены. Основные сборки, содержащие элементы управления, это System.Windows.Controls.dll, System.Windows.Controls.Data.DataForm.dll, System.Windows.Controls.Navigation.dll, System.Windows.Controls.Data.dll, System.Windows.Controls.Input.dll;
- элементы, которые входят в Toolkit, развиваемый как OpenSource проект на codeplex.com (http://www.codeplex.com/silverlight). Нужно отметить, что многие из этих элементов мигрируют в официальный SDK сразу после стабилизации, но Toolkit развивается довольно динамично, поэтому разработчики могут найти что-то интересное для себя;
- платные элементы управления – сегодня существует множество компаний, которые предлагают свои библиотеки.
Элемент ChildWindows позволяет Вам достаточно оперативно создать всплывающее окно, блокирующее весь остальной интерфейс. Если Вы используете Visual Studio, то для создания простейшего окна достаточно добавить в проект новый элемент на основе шаблона SilverLight Child Window. Данный шаблон создает XAML файл, описывающий Child окно и ассоциированный с ним код:
.XAML файл
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
Width="400" Height="300"
Title="ChildWindow1">
.CS файл
public partial class ChildWindow1 : ChildWindow<br />{<br /> public ChildWindow1()<br /> {<br /> InitializeComponent();<br /> }<br /><br /> private void OKButton_Click(object sender, RoutedEventArgs e)<br /> {<br /> this.DialogResult = true;<br /> }<br /><br /> private void CancelButton_Click(object sender, RoutedEventArgs e)<br /> {<br /> this.DialogResult = false;<br /> }<br />}
Инициировать вызов такого окна достаточно просто:
ChildWindow1 child = new ChildWindow1();
child.Show();
Следующий элемент представляет собой распахивающуюся панель.
Поскольку Expander является наследником от HeaderedContentControl, Вы можете использовать более сложный формат для создания заголовка и содержимого:
Используя этот механизм Вы можете установить в качестве заголовка любое содержимое.
Элемент HeaderedContentControl можно использовать как самостоятельный элемент:
Если Вы хотите отобразить набор повторяющихся элементов с заголовком, Вы можете использовать HeaderedItemsControl:
Пример выше вряд ли может показаться интересным, а вот биндинг с динамическим набором элементов значительно интересней:
itemsCol.ItemsSource = new string[] { "Sunday", "Monday", "Tuesday" };
Следующий элемент управления, это TreeView. Как и другие элементы управления TreeView позволяет в качестве элементов дерева использовать любой контент.Вот пример использования элемента.
В отличии от предыдущих элементов, элемент AutoCompleteBox находится в сборке System.Windows.Controls.Input.dll. Этот элемент позволяет отобразить поле для ввода текста и предоставляет возможность динамически установить массив строк для отображения подсказок и автоматического заполнения. Вот пример использования:
box.ItemsSource = new string[] { "Sunday", "Monday", "Tuesday" };
Элемент управления Label позволяет отобразить “надпись”. В отличии от TextBlock элемент Label способен отображать любой контент в качестве метки. Вот пример использования:
На всех семинарах мне задают один и тот же вопрос: Вы анонсировали GPU оптимизацию, но мы не смогли заметить разницу.
На самом деле, если разработчик не выполнит ряд действий, которые почему-то пока не описаны в документации, никакой работы через GPU в его приложении не будет. Давайте посмотрим, что же необходимо сделать для включения оптимизации с помощью GPU.
1). Оптимизация через GPU делает в SilverLight только первые шаги и не предоставляет пока много возможностей. На графический процессор можно пока расчитывать только в двух случаях: при отображении видео и при отображении растровых изображений. При этом речь идет не столько о простом отображении картинки или видео, как об использовании ряда эффектов.
Фактически можно выделить три типа эффектов, которые поддерживаются в бета 1: а). трансформации изображения, б). урезание прямоугольной части изображения, с). смешивание пикселей в области медиа элемента или рисунка (отображение каки-то рекламных вставок, панели инструментов, управление прозрачностью).
2). GPU поддерживается только на Windows платформе. Совершенно не важно, работает ваше приложение в окне браузера или в полноэкранном режиме. Если говорить о Mac, то тут поддержка осуществляется только в полноэкранном режиме. При этом ваша видеокарта должна поддерживать DirectX9.0C или выше.
3). Для включения оптимизации с помощью GPU необходимо:
а) задать эту опцию при создании плагина с помощью параметра EnableGPUAcceleration.
б) включить оптимизацию для конкретного элемента управления. Это делается с помощью свойства CacheMode, которое должно быть установлено в значение BitmapCache.
При этом свойство автоматически устанавливается и для всех дочерних элементов дерева.
Если Вы хотите посмотреть, в каких из областей экрана работает оптимизация с помощью GPU добавьте еще один элемент к параметрам плагина:
RenderForAnimationРаз уж я завел речь об оптимизации, то хочу сделать акцент на новом свойстве RenderOptions.TextRenderingMode, которое применимо к элементам, отображающим текст. Дело в том, что в SilverLight работает достаточно сложный процесс, который оптимизмрует отображение текста, занимаясь его сглиживанием. Но если вы используете текст для анимации, то выглядит это не всехгда впечатляюще. Часть фреймов могут теряться, текст выглядит подергивающимся. Свойство RenderOptions.TextRenderingMode, установленное в значение RenderForAnimation позволяет отключить оптимизацию при отображении текста и тем самым ускорить анимацию.
Smooth StreamingЧтобы увидеть Smooth Streaming в действии, посетите сайт http://www.smoothhd.com/. Рекомендую перейти в раздел Blender и посмотреть видео Big Bucks Bunny:)
Итак, при доставке видео клиенту существует несколько проблем: 1). у пользователя может быть плохой канал, который недостаточен для отображения видео в текущем разрешении; 2). у пользователя может быть загружен процессор, что не позволит ему справится с отображением видео; 3). параметры нагрузки на канал и процессор пользователя регулярно меняются. Имея эти проблемы выложить несколько вариантов ролика, предназначенного на различные каналы явно недостаточно.
Чтобы справится с проблемой IIS 7 Media Service представляет специальное расширение Smooth Streaming.
Идея Smooth Streaming состит в том, что Media service располагает сразу несколькими вариантами видео фрагмента (1280х720, 1024х768 и т. д.) и транслирует видео клиенту небольшими порциями, выбирая наиболее подходящий вариант, базируясь на параметрах канала.
Естественно, чтобы доставлять видео хорошего разрешения с помощью Smooth Streaming необходимо преобразовать исходный файл, сгенерировав различные варианты потоков. Для этого можно использовать Microsoft Expression Encoder 2 SP1, который поддерживает специальный шаблон Adaptive Streaming и позволяет генерировать до 10 потоков.
Далее остается только установить расширение в IIS и передать поток в SilverLight. MediaElement в SilverLight 3 уже поддерживает эту функциональность.
Дополнительно о том, как настроить Smooth Streaming в IIS вы можете узнать по ссылке:
http://www.iis.net/extensions/SmoothStreaming
Работа с эффектами
Начнем с двух встроенных эффектов, это BlurEffect и DropShadowEffect. Эти эффекты позволяют размыть заданную область и отобразить тень соответственно. Рассмотрим простой пример:
Maximum="50"
Value="{Binding Path=Radius, ElementName=blurEf, Mode=TwoWay}">
Тут мы исользуем BlurEffect для “размытия” видео изображения.
Обратите внимание на то, что элемент Effect может содержать лишь один эффект и не позволяет работать с коллекцией элементов. В то же время эффекты можно применять к любым элементам в SilverLight. Поэтому, если Вы хотите применить несколько эффектов, то просто используйте контейнеры. Следующий пример демонстрирует, как для нашего видео добавить эффект тени:
Value="{Binding Radius, ElementName=blurEf, Mode=TwoWay}">
Value="{Binding ShadowDepth, ElementName=shadowEf, Mode=TwoWay}">
Вот что мы получим после запуска приложения:
Представленными двумя эффектами и ограничивается механизм встроенных эффектов, но разработчик может создать свои произвольные эффекты. Рассмотрим пример создания собственного эффекта.
Собственные эффекты описывают с помощью специального языка HLSL. Это самый сложный шаг в создании эффекта, но если Вам повезет, то Вы найдете уже готовое описание. Так, ниже приводится описание эффекта, создающего волну для области.
sampler2D Input : register(s0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 Color;
uv.y = uv.y + (sin((uv.x)*200)*0.01);
uv.x = uv.x + (cos((uv.y)*200)*0.01);
Color = tex2D(Input, uv.xy);
return Color;
}
Обычно описания эффектов хранят в файлах с расширением .fx. Чтобы подготовить эффект к использованию в WPF или SilverLight, HLSL код необходимо сначало откомпилировать. Это можно сделать с помощью утилиты fxc.exe, которая входит в состав DirectX SDK.
Откомпилировав эффет выше и получив файл .ps (от Pixel Shader), добавьте его в проект в виде ресурса.
Остается создать класс, который бы загружал наш эффект и объект которого можно было бы использовать в нашем коде. Вот пример реализации такого класса:
public class WaveEffect : ShaderEffect
{
public WaveEffect()
{
PixelShader = _shader;
UpdateShaderValue(InputProperty);
}
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
public static readonly DependencyProperty InputProperty =
ShaderEffect.RegisterPixelShaderSamplerProperty(
"Input",
typeof(WaveEffect),
0);
private static PixelShader _shader =
new PixelShader() { UriSource = new Uri(
"SilverlightApplication51;component/WaveEffect.ps", UriKind.Relative) };
}
Основная задача, которую вы решаете, описывая класс эффекта, это загрузка эффекта и объявление свойств, понятных для SilverLight, которые связаны со свойствами, описанными в эффекте.
Добавив еще один контейнер в наше приложение, используем созданный эффект:
В результате получим следующее приложение:
Простая анимация
В SilverLight существует несколько типов анимации, один из которых DoubleAnimation. Этот тип анимации способен менять любое цифровое свойство обекта, переводя его значение из одного состояния в другое за некоторый промежуток времени. При этом свойство может менять значение как с линейной скоростью, так и по некоторому сплайну. Между тем, если Вы хотели описать изменение свойства какой-то сложной функцией, то приходилось комбинировать несколько фреймов в анимации.
Например, чтобы выполнить анимацию для мячика, падающего на поверхность, использовать один объект анимаци было недостаточно. Так, очень сомнительно, что мячик упадет на поверхность и не подскочет вверх. Если же Вы хотели увидеть прыгающий мячик, то Вам бы пришлось реализовывать каждый скачек в виде отдельного фрейма, что значительно бы увеличило код и сложность приложения.
SilverLight 3 включает несколько полезных функций, которые позволяют решать ряд распространенных задач. Ниже показан код, который использует функцию, позволяющую достичь эффекта прыгающего мячика:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" Loaded="UserControl_Loaded">
Storyboard.TargetProperty="(Canvas.Top)"
Duration="0:0:5">
На текущий момент существует 11 простых функций анимации. Вот полный список: ExponentialEase, PowerEase, QuadraticEase, BackEase, BounceEase, CircleEase, CubicEase, ExponentialEase, PowerEase, QuadraticEase, ElasticEase, QuarticEase, QuinticEase, SineEase.
Каждая из функций имеет свои параметры, позволяющие задать коэффициенты уравнения. Кроме того, с помощью специального свойства EasingMode можно с легкостью получить зеркальное отображение функции.
Вот как выглядят некоторые из них в графическом представлении (EaseOut, EaseIn, EaseInOut):
ElasticEase
QuarticEase
QuinticEase
SineEase
Между тем, если Вы используете Expression Studio для построения интерфейса, то Вам не нужно запоминать названия и соответствующие графики для каждой из функций. Вы можете воспользоваться визуальной посказкой, что делает использование простых функций анимации действительно простым.
Улучшенная работа с изображениями, системные цвета
Поддержка системных цветовSilverLight 3 поддерживает статический класс SystemColors с набором цветов, зависимых от локальных настроек пользователя. Это такие цвета как Menu, ActiveCaption, InactiveWindow и др. Использование этих цветов возможно применительно к любому из UI элементов:
. . . = new SolidColorBrush(SystemColors.ControlDarkColor);
Улучшенная работа с кешемЭлемент BitmapImage поддерживает дополнительное значение свойства CreateOptions - CreateOptions="IgnoreImageCache".
Это свойство позволяет выключить кеш при загрузке изображений. Примером, где это действительно нужно, может служить AntiSpam control, который генерирует изображение для ввода пользователем, предоствращающее реализацию скрипта, автоматически заполняющего форму. Обычно такой элемент управления присутствует на страницах регистрации. Если пользователь ввел данные, представленные AntiSpam элементов неправильно, то элемент должен перегенерировать содержимое и предоставить пользователю следующую попытку. Но при включенном кеше пользователь не сможет увидеть новую версию того же изображения и система регистрации не будет работать.
ImageOpened, MediaOpenedСобытия ImageOpened у BitmapImage и MediaOpened у MediaElement позволяют реализовать код по работе с изображением (или видео), когда изображение не просто было загружено по сети, но и полностью декодировано. Так, если изображение загружено на 100%, это не означает, что программист может получить доступ к свойствам Width и Height. Данные события снимают проблему.
Pixel API
Кто-то на одном из семинаров спрашивал меня о том, как можно сделать скриншот интерфейса SilverLight приложения и сохранить его в виде изображения на диск. С этого примера и начнем.
Для начала создадим интерфейс приложения, состоящий из примитивной формы и панели для отображения нашего снимка:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="600">
Чтобы пример был более эффектным, будем делать снимок не просто формы, а всего интерфейса, включая и панель со снимком. Чтобы реализовать такой код, нам понадобится класс WritableBitmap. Вот он то и представляет собой реализацию Pixel API в SilverLight 3. Этот класс содержится в пространстве имен System.Windows.Media.Imaging и позволяет создать Bitmap контекст заданного размера (длина, ширина изображения). Доступ к изображению может быть осуществлен попиксельно, используя простой индексатор.
В нашем примере мы используем метод Render, который позволяет преобразовать в изображение любой графический элемент, включая его дочерние элементы.
private void Button_Click(object sender, RoutedEventArgs e)
{
WriteableBitmap bit = new WriteableBitmap(this.Width, this.Height, PixelFormats.Pbgra32);
bit.Render(LayoutRoot, new MatrixTransform());
Image img = new Image();
img.Source = bit;
stk1.Children.Clear();
stk1.Children.Add(img);
}
Вот так будет выглядить наше приложение после многократного нажатия кнопки Update.
Улучшения при связывании элементов с данными
SilverLight 3 позволяет с легкостью связывать свойства различных элементов управления, используя только XAML код.
Фактически мы использовали эту возможность в разделе, посвященном 3D проекциям. Вот как выглядил наш код:
Тут мы связали свойство RotationX элемента projection с текущим значением Slider. Как видите, тут используется довольно простая конструкция.
Local Connection
Рассмотрим пространство имен System.Windows.Messaging, которое позволяет наладить взаимодействие между несколькими приложениями SilverLight.
Создадим простое приложение, которое отображает эллипс двигающийся снизу вверх:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" Loaded=”UserControl_Loaded”>
From="300" To="-30" Duration="0:0:5">
Запуск анимации будет происходить при загрузке главного контейнера:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
sb1.Begin();
}
Создайте второе приложение, которое будет содержать точно такой же код, за исключением метода UserControl_Loaded. Разместите приложения на HTML странице следующим образом:
Давайте попробуем реализовать код прриложений таким образом, чтобы после окончания анимации в приложении 1, запускалась анимация во втором приложении. Таким образом, мы должны достигнуть эффета, когда наш шарик будет “перелетать” из одного приложения в другое.
Реализуем следующий код в первом приложении:
LocalMessageSender msgSender = new LocalMessageSender("DownSide");
public MainPage()
{
InitializeComponent();
LocalMessageReceiver receiver = new LocalMessageReceiver("UpSide");
receiver.MessageReceived += new EventHandler
receiver.Listen();
}
void receiver_MessageReceived(object sender, MessageReceivedEventArgs e)
{
sb1.Begin();
}
private void sb1_Completed(object sender, EventArgs e)
{
msgSender.SendAsync("start");
}
Тут мы создали объект типа LocalMessageSender, в задачи которого входит отправка сообщения “слушателю” с указанным именем (DownSide, наверное стоило назвать по другому). Этот метод отправляет сообщение сразу после окончания анимации с помощью метода SendAsync (фактически передает управление другому приложению).
Объект LocalMessageReceiver, напротив, ожидает сообщение от других приложений. Как только сообщение приходит (второе приложение закончило анимацию), то тут же анимация запускается повторно (полетел еще один шарик).
Код во втором приложении выглядит аналогично:
LocalMessageSender msgSender = new LocalMessageSender("UpSide");
public MainPage()
{
InitializeComponent();
LocalMessageReceiver receiver = new LocalMessageReceiver("DownSide");
receiver.MessageReceived += new EventHandler
receiver.Listen();
}
void receiver_MessageReceived(object sender, MessageReceivedEventArgs e)
{
sb1.Begin();
}
private void sb1_Completed(object sender, EventArgs e)
{
msgSender.SendAsync("start");
}
Откомпилировав и запустив данный пример, мы получим желаемый эффект:
Следует отметить, что если Ваши приложения загружаются из различных доменов, то наладить взаимодействие между ними также возможно. Для этого просто следует указать имя домена в конструкторе классов LocalMessage…
Ссылки и литература
- Блог Andy Beauliue
- Brad Adams - http://blogs.msdn.com/brada/default.aspx
- Chris Hay http://www.screencast.com/users/chrishayuk
- DotNet Curry http://www.dotnetcurry.com/
- Jesse Liberty http://silverlight.net/blogs/jesseliberty/
- Joe Stegman http://blogs.msdn.com/jstegman/default.aspx
- Nikola Mihaylov http://blogs.msdn.com/nikola/default.aspx
- Page Brooks http://pagebrooks.com/
- Pete Brown http://community.irritatedvowel.com/blogs/pete_browns_blog/default.aspx
- Silverlight Learning Resources http://silverlight.net/learn/
- SilverlightShow http://www.silverlightshow.net/
- Terence Tsang http://www.shinedraw.com/
- Tim Heuer http://timheuer.com/blog/
- Timmy Kokke http://geekswithblogs.net/tkokke/Default.aspx
- Rick Boarman http://www.netvibes.com/rboarman#Silverlight
- Официальный сайт - http://silverlight.net/
- Все о Microsoft Silverlight - http://silverlightru.net/
- Блог для дизайнеров (Siverlight / WPF / Blend) - http://dev.net.ua/blogs/helen/
Компании из статьи
Microsoft Украина | Украинское подразделение компании Microsoft. |