пятница, 21 июня 2013 г.

Как сделать страницу со своим меню в Windows Store приложении

Как и многие из последних статей, эта является ответом на вопрос с форумов MSDN. Стоит задача сделать пункты, выбрав один из которых пользователь будет переходить на нужную страницу. Говорят, так сделано приложение твиттера, ну и таким подходом предполагается воспользоваться, т.к. верхний и нижний AppBar уже заняты.

Этот подход оправдан, если страницы уже есть, переделывать их в UserControl лениво, и хочется на них добавить меню.
Я создал пустое приложение и добавил в него еще две страницы. Т.к. это всего лишь пример, то на страницы я добавляю по TextBlock-у с текстом, что это за страница. Вот пример главной страницы:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="1"  Text="Это главная страница" FontSize="20" />
</Grid>

 Правый клик на проекте, добавить новый элемент, UserControl. Я с названием заморачиваться не стал и назвал компонент MyMenu. Вот разметка, которую я поместил в XAML:
<UserControl
    x:Class="App3.MyMenu"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:local="using:App3"
    xmlns:d=http://schemas.microsoft.com/expression/blend/2008
    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">   
    <ListView x:Name="lvMain">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <TextBlock>Главная</TextBlock>
        <TextBlock>Первая</TextBlock>
        <TextBlock>Вторая</TextBlock>
    </ListView>
</UserControl>
Как видите, ничего сложного. Ну и код этого контрола:

public sealed partial class MyMenu : UserControl
{
    public MyMenu()
    {
        this.InitializeComponent();
        Loaded += MyMenu_Loaded;
    }
 
    Type[] pages = { typeof(MainPage), typeof(BlankPage1), typeof(BlankPage2) };
 
    void MyMenu_Loaded(object sender, RoutedEventArgs e)
    {
        Page currentPage = GetCurrentPage();
        lvMain.SelectedIndex = pages.TakeWhile(p => p != currentPage.GetType()).Count();
        lvMain.SelectionChanged += lvMain_SelectionChanged;
    }
 
    void lvMain_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Page currentPage = GetCurrentPage();
        if (currentPage.GetType() != pages[lvMain.SelectedIndex])
        {
            currentPage.Frame.Navigate(pages[lvMain.SelectedIndex]);
        }
    }
 
    private Page GetCurrentPage()
    {
        FrameworkElement element = this;
        while (element != null && element.Parent != null && !(element.Parent is Page))
        {
            element = element.Parent as FrameworkElement;
        }
        Page currentPage = element.Parent as Page;
        return currentPage;
    }
}

Здесь я завожу массив с типами страниц, на которые надо переходить. Дописываю вспомогательный метод, чтобы находить ссылку на страницу в которой размещен мой контрол. При заходе на страницу подсвечиваю соответствующий элемент списка, а при выборе элемента списка, переходжу на страницу с нужным индексом.
Все, осталось мелочи. Компилируем проект и прямо из панели Toolbox перетягиваем наш новый контрол в XAML всех страниц:
Должно получиться как то так:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <local:MyMenu />
    <TextBlock Grid.Row="1"  Text="Это главная страница" FontSize="20" />
</Grid>

Все. Запускаем и видим вот такую работу:
Все.

Комментариев нет:

Отправить комментарий