Application Bar

Всем добрый вечер!

Это девятая статья из цикла Windows Phone 7 для начинающих. Сегодня мы поговорим об Application Bar. Я не стал переводить это название, так как оригинальное название лучше отражает суть. Вообще, это довольно простая, но, невероятно практичная идея! Поместить основные действия приложения в одно место, которое будет всегда доступно. Как, например, форма входа. Пользователю всегда важно и нужно видеть кнопку "Вход" или "Отмена", а клавиатура может все перекрыть. Потому кнопки и помещаются в Application Bar. Подробнее о форме входа и Application Bar читаем тут.

Давайте создадим небольшой Видео плеер, у которого будет Application Bar.

Вот как будет выглядеть страница MainPage.xaml:

<phone:PhoneApplicationPage
    x:Class="day_9_application_bar.MainPage"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="false">
<phone:PhoneApplicationPage.ApplicationBar >
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
        <shell:ApplicationBarIconButton Text="Назад" x:Name="Rewind" Click="Rewind_Click"/>
        <shell:ApplicationBarIconButton Text="Играть" x:Name="Play" Click="Play_Click"/>
        <shell:ApplicationBarIconButton Text="Пауза" x:Name="Pause" Click="Pause_Click"/>
        <shell:ApplicationBarIconButton Text="В конец" x:Name="End" Click="End_Click"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="0">
        <TextBlock x:Name="ApplicationTitle" Text="Блог Антона Полховского" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="Title" TextAlignment="Center" Text="Видео плеер" Style="{StaticResource PhoneTextNormalStyle}"/>
    </StackPanel>
<!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <MediaElement Name="mediaElement" Source="http://www.charlespetzold.com/Media/Walrus.wmv" AutoPlay="False"
MediaOpened="OnMediaElementMediaOpened" MediaFailed="OnMediaElementMediaFailed" CurrentStateChanged="OnMediaElementCurrentStateChanged" />
        <TextBlock Name="statusText" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
        <TextBlock Name="errorText" HorizontalAlignment="Right"
VerticalAlignment="Bottom"
TextWrapping="Wrap" />
    </Grid>
</Grid>
</phone:PhoneApplicationPage>

Используем видео файл Чарльза Петзольда для демонстрации, ссылку на который он дает в своей книге. В этом коде мы создаем ApplicationBarIconButton, но без пути к картинке. Что бы добавить правильную картинку, необходимой перейти к Expression Blend из студии. Как это сделать мы обсуждали на втором дне. В Objects и Timeline выбираем Application Bar и видим в дереве кнопки. Выбираем одну из кнопок и в свойствах видим поле IconUri которое является пустым. Если нажать на "...", то мы попадем в папку, где хранятся все иконки. Перед созданием своих, подробно изучите принципы построения этих, и создайте свои по образу и подобию, не нарушая при этом цветов. Если же вы нажмете на выпадающий список, то увидите стандартные иконки.

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

Тут есть одна загвоздка: нельзя же что бы кнопка Пауза была доступна одновременно с кнопкой Играть. Для этого существует свойство IsEnabled, которое и позволяет нам сделать кнопку недоступной. Сделаем их все недоступными. А в коде будем решать когда и какая из них будет доступна. Вообще это довольно трудоемко определять, когда и какая кнопка будет доступна. Потому я немного все упростил, допустив, что кнопки В конец и Назад будут доступны когда видео загружено, а Пауза и Играть будут исключать друг друга. Кроме явного указания атрибута x:Name для каждой кнопки в Application Bar есть еще альтернативный способ доступа. Я использую его. Вот код страницы MainPage.xaml.cs:

using System;
using System.Windows;
using System.Windows.Media;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace day_9_application_bar
{
    public partial class MainPage : PhoneApplicationPage
    {
        private ApplicationBarIconButton PlayButton;
        private ApplicationBarIconButton RewindButton;
        private ApplicationBarIconButton EndButton;
        private ApplicationBarIconButton PauseButton;

        public MainPage()
        {
            InitializeComponent();

            RewindButton = this.ApplicationBar.Buttons[0] as ApplicationBarIconButton;
            PlayButton = this.ApplicationBar.Buttons[1] as ApplicationBarIconButton;
            PauseButton = this.ApplicationBar.Buttons[2] as ApplicationBarIconButton;
            EndButton = this.ApplicationBar.Buttons[3] as ApplicationBarIconButton;
        }

        private void Rewind_Click(object sender, EventArgs e)
        {
            mediaElement.Position = TimeSpan.Zero;
        }

        private void Play_Click(object sender, EventArgs e)
        {
            mediaElement.Play();
        }

        private void Pause_Click(object sender, EventArgs e)
        {
            mediaElement.Pause();
        }

        private void End_Click(object sender, EventArgs e)
        {
            mediaElement.Position = mediaElement.NaturalDuration.TimeSpan;
        }

        private void OnMediaElementMediaOpened(object sender, RoutedEventArgs e)
        {
            RewindButton.IsEnabled = true;
            EndButton.IsEnabled = true;
        }

        private void OnMediaElementMediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            errorText.Text = e.ErrorException.Message;
        }

        private void OnMediaElementCurrentStateChanged(object sender, RoutedEventArgs e)
        {
            statusText.Text = mediaElement.CurrentState.ToString();
            if (mediaElement.CurrentState == MediaElementState.Stopped || mediaElement.CurrentState == MediaElementState.Paused)
            {
                PlayButton.IsEnabled = true;
                PauseButton.IsEnabled = false;
            }
            else if (mediaElement.CurrentState == MediaElementState.Playing)
            {
                PlayButton.IsEnabled = false;
                PauseButton.IsEnabled = true;
            }
        }
    }
}

Единственный минус - эмулятор не очень дружит с интернетом. В примере представлена альтернативная ссылка на видео поменьше. Код можно скачать тут.

День #10. Немного о панораме. Программный контроль.