Here's a clear(ish) example. It's written in C# with the viewmodels in the code behind so the demo can better focus on the issue.
Start a new WPF project in C# and call it FrameInFrame.
MainWindow simply contains a frame with its content Uri set to MainPage.xaml. It has no code behind.
<Window x:Class="FrameInFrame.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FrameInFrame"
Title="Main Window">
<Frame Source="MainPage.xaml"/>
</Window>
<Page x:Class="FrameInFrame.MainPage"
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:local="clr-namespace:FrameInFrame"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Page.Resources>
<RoutedCommand x:Key="LoadCommand"/>
</Page.Resources>
<Page.CommandBindings>
<CommandBinding Command="{StaticResource LoadCommand}" Executed="LoadCommand_Executed"/>
</Page.CommandBindings>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Load Subpage 2" Command="{StaticResource LoadCommand}"/>
<Frame Grid.Column="1" Source="{Binding FrameSource}"/>
</Grid>
</Page>
using System;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Input;
namespace FrameInFrame
{
public partial class MainPage : Page, INotifyPropertyChanged
{
private string _FrameSource = "SubPage1.xaml";
public string FrameSource
{
get { return _FrameSource; }
set
{
if (_FrameSource != value)
{
_FrameSource = value;
NotifyPropertyChanged("FrameSource");
}
}
}
public MainPage()
{
InitializeComponent();
}
private void LoadCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
FrameSource = "SubPage2.xaml";
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}
Lastly add a page called SubPage1 and one called SubPage2. They don't have any code behind. The XAML for SubPage1 is below. I think you can guess what the XAML for SubPage2 looks like.
<Page x:Class="FrameInFrame.SubPage1"
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:local="clr-namespace:FrameInFrame">
<TextBlock Text="Sub Page 1"/>
</Page>
Now run the project and click the button. SubPage2 is loaded and the text changes to reflect this. The frame defined in MainWindow now shows navigation buttons. Even though the MainPage frame did the navigation, the MainWindow frame is handling the navigation. This is the default behavior.
Now change the MainPage frame to look like this, and run the program again.
<Frame Grid.Column="1" Source="{Binding FrameSource}" JournalOwnership="OwnsJournal"/>
Now the inner frame uses it's own navigation service and you can navigate the inner frame without affecting the outer frame's navigation service.
No comments:
Post a Comment