Переключение между страницами в 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>
Посмотрите, поможет ли это.