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. Немного о панораме. Программный контроль.