Переключение между страницами в WPF

Я хочу сделать макет, подобный тому, который используется на любом веб-сайте - верхний и нижний колонтитулы остаются такими же, но центральная часть. У меня есть несколько страниц / окон для отображения в приложении Wpf blend C#, и они совершенно разные. Например, в stackru есть макет для домашней страницы и еще один для каждого вопроса. Вот еще один пример:

первая страницавторая страница

Я должен был сделать это в предыдущем проекте, и я использовал один макет сетки, а затем для каждой страницы мне пришлось скрыть () все из них и показать, что каждый сверху -

В чем подвох? Как я могу сделать то же самое в приложении wpf? В типичном приложении на C# мне каждый раз приходилось бы открывать дочернее окно, но в наши дни это выглядит ужасно.

Заранее спасибо!

3 ответа

Решение

Если вы собираетесь использовать Page s в WPF, вам нужно будет прочитать страницу обзора навигации в MSDN. Короче говоря, вы можете перемещаться между Page в приложении WPF с помощью NavigationService Класс Чтобы изменить страницу из кода, вы можете сделать что-то вроде этого:

NextPage page = new NextPage();
NavigationService.Navigate(page);

Чтобы пользователи могли изменить Page, вы можете использовать Hyperlink Класс в вашем Page s:

<Hyperlink NavigateUri="pack://application:,,,/AppName;component/Pages/NextPage.xaml">
    Navigate to Next Page
</Hyperlink>

Чтобы получить желаемую настройку страницы, вам нужно будет загрузить Pageс в Frame, который вы можете затем разметить, где вы хотите в MainWindow.xaml:

<Frame Source="pack://application:,,,/AppName;component/Pages/SomePage.xaml" />

Похоже, вам нужен пользовательский контроль пользователя и некоторые привязки данных.

Вы можете объявить DataTemplates в XAML как ресурсы с типом модели в качестве ключа, чтобы WPF автоматически выбрал правильный DataTemplate:

  • Иметь основную ViewModel, которая предоставляет свойство ImageSourceViewModel. Это свойство будет возвращать CameraSourceViewModel или FileSourceViewModel, в зависимости от ситуации.

  • На вашей странице DataContext будет основной ViewModel, и у вас будет XAML, например:

Затем,

<Page x:Class="Page1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:my="clr-namespace:WpfApplication1"
  mc:Ignorable="d" 
  d:DesignHeight="300" d:DesignWidth="300"
  Title="Page1">
<Page.Resources>
    <DataTemplate DataType="{x:Type my:CameraSourceViewModel}">
        <my:CameraSourceView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type my:FileSourceViewModel}">
        <my:FileSourceView/>
    </DataTemplate>
</Page.Resources>
<Grid>
    <ContentControl Content="{Binding ImageSourceViewModel}"/>
</Grid>

Я должен указать, что этот пример использует шаблон MVVM, чтобы позволить слою viewmodel принимать решение о содержимом в середине. Надеюсь, это достаточно ясно, если нет, дай мне крик, и я постараюсь расширить его!

Допустим, у меня есть модель основного вида, где я создал свойство CurrentPage, которое сообщит, какую страницу вы хотите отобразить.

/// <summary>
/// Returns the page ViewModel that the user is currently viewing.
/// </summary>
public ViewModelBase CurrentPage
{
    get { return _currentPage; }
    private set
    {
        if (value != _currentPage)
        {
            if (_currentPage != null)
                _currentPage.IsCurrentPage = false;

            _currentPage = value;

            if (_currentPage != null)
                _currentPage.IsCurrentPage = true;
            RaisePropertyChanged(() => CurrentPage);
        }
    }
}

И в вашем xaml вы можете связать свою страницу под некоторым контролем. Допустим, я делаю это внутри элемента Border.

<!-- CURRENT PAGE AREA -->
<Border Background="White" Grid.Column="1" Grid.Row="0">
    <HeaderedContentControl Content="{Binding Path=CurrentPage}" 
        Header="{Binding Path=CurrentPage.DisplayName}" />
</Border>

Вы можете определить представление для вашей модели представления в ресурсах так:
(частично полный XAML)

<UserControl x:Class="BAT.View.BATWizardView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:view="clr-namespace:BAT.View"
        xmlns:viewmodel="clr-namespace:BAT.ViewModel"
        mc:Ignorable="d" 
        d:DesignHeight="350" d:DesignWidth="600">

   <UserControl.Resources>
      <!-- These four templates map a ViewModel to a View. -->
      <DataTemplate DataType="{x:Type viewmodel:MyComparisonViewModel1}">
          <view:MyView1 />
      </DataTemplate>

      <DataTemplate DataType="{x:Type viewmodel:MyComparisonViewModel2}">
          <view:MyView2 />
      </DataTemplate>

   </UserControl.Resources>
   <Grid>
      <Border Background="White" Grid.Column="1" Grid.Row="0">
         <HeaderedContentControl Content="{Binding Path=CurrentPage}" 
                      Header="{Binding Path=CurrentPage.DisplayName}" />
      </Border>
   </Grid>
</UserControl>

Посмотрите, поможет ли это.

Другие вопросы по тегам