Share via


SilverLight 3: Что нового? (часть 1)

В то время, как в Лас-Вегасе открывается конференция MIX09, я еду в поезде в сторону Минска, где планирую сделать первый доклад о технологии SilverLight 3. К тому моменту, как я сойду с поезда, подключусь в Интернет и опубликую эту статью, Вы уже должны иметь возможность загрузить этот продукт из сети в версии Beta 1. Кроме того, если Вы не смогли попасть в Лас-Вегас (может мы едем в одном поезде), то сможете получить доступ к записанным видео-трансляциям с конференции в течении следующих 24 часов. Именно по этой причине я не решаюсь дать краткий обзор возможностей SilverLight 3, а сразу перейду к написанию кода, сосредоточившись лишь на некоторых аспектах (пока меня не отвлекут таможенники с вопросом "Что везете? Сервелат? 3 ящика? А колбасу нужно сдать.").

Итак,...

3D проекции

Естественно, что реализовать механизм полноценного 3D движка в плагине размером 4-6 Мб достаточно тяжело. Между тем псевдо 3D позволяет реализовать множество различных сценариев, но требует от разработчика значительное количество усилий. Благодаря элементу PlaneProjection в SilverLight 3 разработчик может стоить простые проекции, указав всего несколько параметров. Рассмотрим простой код, отображающий MediaElement:

<UserControl x:Class="SilverlightApplication30.MainPage"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot" Background="White" VerticalAlignment="Center">
        <MediaElement Source="4.wmv" Width="500" Height="300">
            <MediaElement.Projection>
                <PlaneProjection x:Name="projection" RotationY="60"></PlaneProjection>
            </MediaElement.Projection>
        </MediaElement>
    </StackPanel>
</UserControl>

В результате мы получим MediaElement "повернутый" на 60 градусов по оси Y.

image

Тут мы использовали элемент PlaneProjection с атрибутом RotationY. Логично, что если Вы хотите развернуть изображение по другим осям, то нужно воспользоваться атрибутами (свойствами) RotationX, RotationZ. Элемент PlaneProjection можно использовать по отношению к любому из элементов-наследников от UIElement.

Добавим к нашему коду 4 слайдера, чтобы изменять угол вращения по запросу пользователя:

<UserControl x:Class="SilverlightApplication30.MainPage"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot" Background="White" VerticalAlignment="Center">
        <MediaElement Source="4.wmv" Width="500" Height="300">
            <MediaElement.Projection>
                <PlaneProjection x:Name="projection" ></PlaneProjection>
            </MediaElement.Projection>
        </MediaElement>
        <Slider Width="588" Minimum="0" Maximum="360" Value="{Binding RotationX, Mode=TwoWay, ElementName=projection}"></Slider>
        <Slider Width="588" Minimum="0" Maximum="360" Value="{Binding RotationY, Mode=TwoWay, ElementName=projection}"></Slider>
        <Slider Width="588" Minimum="0" Maximum="360" Value="{Binding RotationZ, Mode=TwoWay, ElementName=projection}"></Slider>
        <Slider Width="588" Minimum="0" Maximum="300" Value="{Binding LocalOffsetZ, Mode=TwoWay, ElementName=projection}"></Slider>
    </StackPanel>
</UserControl>

В этом примере мы воспользовались еще одним свойством LocalOffsetZ. Свойства LocalOffsetX, LocalOffsetY, LocalOffsetZ позволяют разместить объект в трехмерном пространстве. Как пример использования этих свойств можно рассмотреть "карусель", где все объекты кроме одного расположны на некотором удалении. Кроме этих свойств существуют еще свойства GlobalOffsetX, GlobalOffsetY, GlobalOffsetZ. Разница между ними только в том, что первые устанавливают смещение относительно текущего контейнера, а вторые - относительно всего окна.

Последние свойства, которые могут быть интересны разработчику, это CenterOfRotationX, CenterOfRotationY, CenterOfRotationZ. Позволяют задать точку, вокруг которой проводить вращение.

О! Мы тронулись и ко мне в шкафчик пришел какой-то бородатый мужик. Мужик - не девушка, поэтому я еще смогу не отвлекаться. Кроме того, он говорит только по английски. Сделаю вид, что я не есть понимать.

Offline работа

Следующая интересная возможность - установка SilverLight приложения в локальный кэш пользователя с возможностью запуска в режиме, отключенном от сети.

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

1). Вызвать метод Detach у объекта Application. При этом данный метод должен быть вызван только из обработчика события, инициируемого пользователем. Например, событие может быть связано с нажатием на кнопку.

Добавим кнопку в предыдущий XAML файл.

<Button Content="Detach" Width="100" Click="Button_Click"></Button>

Разместите кнопку сразу после последнего элемента Slider.

Обработчик нажатия на кнопку будет выглядеть так:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Application.Current.Detach();
}

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

<Deployment xmlns="https://schemas.microsoft.com/client/2007/deployment"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <Deployment.Parts>
    </Deployment.Parts>
    <Deployment.ApplicationIdentity>
        <ApplicationIdentity
            ShortName="Offline App"
            Title="My Title">
            <ApplicationIdentity.Blurb>
              This is my offline App
            </ApplicationIdentity.Blurb>
        </ApplicationIdentity>
    </Deployment.ApplicationIdentity>
</Deployment>

Если Вы хотите также описать и иконки, то добавьте следующий элемент:

<ApplicationIdentity.Icons>
   <Icon Size="16x16">icons/16x16.png</Icon>
   <Icon Size="32x32">icons/32x32.png</Icon>
   <Icon Size="48x48">icons/48x48.png</Icon>
   <Icon Size="128x128">icons/128x128.png</Icon>
</ApplicationIdentity.Icons>

Если иконки явно не указаны, то подставляется иконка по умолчанию.

Теперь можно запустить приложение и нажать на кнопку. На экране появится следующее сообщение:

image 

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

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

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