Pull to refresh

Локализация ApplicationBar с помощью Binding

Reading time6 min
Views3.4K
Когда я учился разрабатывать приложения на основе MVVM мне жутко не понравилось, что во многих статьях показано как ApplicationBar создается во ViewModel. Там же кнопки и элементы меню заполняется локализованными строками. Я долго искал решение, и оно было найдено.
Внимание! Статья описывает только решение проблемы локализации панели приложения и подразумевает что читатели знакомы с основами XAML, MVVM, связыванием данных и локализацией приложений.

Встречайте бибилиотеку для локализации панели приложения: http://appbarutils.codeplex.com/
Что бы попробовать ее в работе создадим страницу приложения и добавим в ней обычную панель приложения, с кнопками и, если необходимо, пунктами меню. Например, такую:
<shell:ApplicationBar>
            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem IsEnabled="True" Text="lookscreen"/>
            </shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarIconButton IconUri="/Assets/AppBar/save.png" IsEnabled="True" Text="save"/>
</shell:ApplicationBar>

Обратите внимание: свойство Text должно быть без пробелов. Работоспособность при наличии кириллицы не проверял.
Добавляем пакет AppBarUtils в приложение командой Install-Package AppBarUtils или через диспетчер пакетов. Добавляем в разметку страницы ссылку на сборку этого пакета:
xmlns:AppBarUtils="clr-namespace:AppBarUtils;assembly=AppBarUtils"

И нам еще понадобится сборка для задания поведений:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

После этих приготовлений задаем поведения для страницы на которой находится панель приложения. У меня получилось вот так:
<i:Interaction.Behaviors>
        <AppBarUtils:AppBarItemCommand Id="save" Type="Button" Command="{Binding SaveCommand}" Text="{Binding LocalizedResources.SaveButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
        <AppBarUtils:AppBarItemCommand Id="lookscreen" Type="MenuItem" Command="{Binding LookScreenCommand}" Text="{Binding LocalizedResources.ScreenItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
    </i:Interaction.Behaviors>

Связывание поведения с элементом, которому он назначен, происходит по ID со значением равным свойству Text пункта меню или кнопки. Кроме того, задается тип элемента меню, которому задается поведение: для кнопки – Button, для пункта меню – MenuItem. Значение остальных свойств пояснять думаю не нужно.
После всех манипуляций у меня получилась страница в реальном приложении, которое опубликовано в windows phone store:
XAML
<phone:PhoneApplicationPage
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
    xmlns:AppBarUtils="clr-namespace:AppBarUtils;assembly=AppBarUtils" 
    x:Class="CatDay.MainPage"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations ="PortraitOrLandscape"
    shell:SystemTray.IsVisible="True"
    DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}">
    <shell:SystemTray.ProgressIndicator>
        <shell:ProgressIndicator IsIndeterminate="true" IsVisible="{Binding ProgressBarValue}" Text="{Binding ProgressBarText}" />
    </shell:SystemTray.ProgressIndicator>

   
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar>
            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem IsEnabled="True" Text="donate"/>
                <shell:ApplicationBarMenuItem IsEnabled="True" Text="lookscreen"/>
                <shell:ApplicationBarMenuItem IsEnabled="True" Text="skydrive"/>
                <shell:ApplicationBarMenuItem IsEnabled="True" Text="feedback"/>
            </shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarIconButton IconUri="/Assets/AppBar/transport.rew.png" IsEnabled="True" Text="previus"/>
            <shell:ApplicationBarIconButton IconUri="/Assets/AppBar/save.png" IsEnabled="True" Text="save"/>
            <shell:ApplicationBarIconButton IconUri="/Assets/AppBar/share.png" IsEnabled="True" Text="share"/>
            <shell:ApplicationBarIconButton IconUri="/Assets/AppBar/transport.ff.png" IsEnabled="True" Text="next"/>            
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

	<i:Interaction.Behaviors>
		<AppBarUtils:AppBarItemCommand Id="next" Type="Button" Text="{Binding LocalizedResources.NextButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Command="{Binding NextImageCommand}"/>
        <AppBarUtils:AppBarItemCommand Id="share" Type="Button" Command="{Binding ShareCommand}" Text="{Binding LocalizedResources.ShareButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
        <AppBarUtils:AppBarItemCommand Id="previus" Type="Button" Command="{Binding PreviusImageCommand}" Text="{Binding LocalizedResources.PreviusButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
        <AppBarUtils:AppBarItemCommand Id="save" Type="Button" Command="{Binding SaveCommand}" Text="{Binding LocalizedResources.SaveButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
        <AppBarUtils:AppBarItemCommand Id="lookscreen" Type="MenuItem" Command="{Binding LookScreenCommand}" Text="{Binding LocalizedResources.ScreenItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
        <AppBarUtils:AppBarItemCommand Id="skydrive" Type="MenuItem"  Command="{Binding SkyDriveCommand}" Text="{Binding LocalizedResources.SkydriveItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}" />
        <AppBarUtils:AppBarItemCommand Id="donate" Type="MenuItem" Text="{Binding LocalizedResources.DonateMenuItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Command="{Binding DonateCommand }"/>
        <AppBarUtils:AppBarItemCommand Id="feedback" Type="MenuItem" Text="{Binding LocalizedResources.FeedbackAppBarButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"  Command="{Binding FeedbackCommand}"/>        
    </i:Interaction.Behaviors>       

    <!--LayoutRoot представляет корневую сетку, где размещается все содержимое страницы-->
	<Grid x:Name="LayoutRoot" Background="Transparent">
		
		<Grid.RowDefinitions>
			<RowDefinition Height="Auto"/>
			<RowDefinition Height="*"/>
		</Grid.RowDefinitions>
		<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
			<TextBlock Text="{Binding LocalizedResources.ApplicationTitle, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextGroupHeaderStyle}" Margin="12,0"/>
		</StackPanel>
	</Grid>
</phone:PhoneApplicationPage>




В конце статьи еще раз укажу ссылку на страницу проекта AppBarUtils, там же много ссылок на примеры использования этой библиотеки, исходники не выложены.

Надеюсь, что эта маленькая статья поможет начинающим разработчикам в локализации приложений, а опытных разработчиков избавит от распространенного заблуждения что панель приложения нельзя локализовать с помощью связывания данных.
Tags:
Hubs:
+2
Comments1

Articles