Start a new WPF project using C# targeting any framework. Call the project GoBack.
The MainWindow will contain some buttons, some text blocks, and a frame. The buttons allow us to navigate the frame and the text blocks will monitor some properties. The xaml looks like this.
<Window x:Class="GoBack.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:GoBack"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<RoutedCommand x:Key="LoadCommand"/>
<RoutedCommand x:Key="BackCommand"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource LoadCommand}" Executed="Load_Executed"/>
<CommandBinding Command="{StaticResource BackCommand}" CanExecute="Back_CanExecute" Executed="Back_Executed"/>
</Window.CommandBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Load Page 2" Command="{StaticResource LoadCommand}" CommandParameter="Page2.xaml"/>
<Button Content="Go Backward" Command="{StaticResource BackCommand}"/>
</StackPanel>
<TextBlock Grid.Row="1" Text="{Binding FrameSource, StringFormat='FrameSource={0}'}"/>
<TextBlock Grid.Row="2" Text="{Binding ElementName=MainFrame, Path=Source, StringFormat ='MainFrame.Source={0}'}"/>
<Frame Name="MainFrame" Grid.Row="3" Source="{Binding FrameSource}" Background="AliceBlue"/>
</Grid>
</Window>
The code behind implements the commands and defines a property that is bound to the Frame's Source property.
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace GoBack
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string _FrameSource = "Page1.xaml";
public string FrameSource
{
get { return _FrameSource; }
set
{
if (_FrameSource != value)
{
_FrameSource = value;
NotifyPropertyChanged("FrameSource");
}
}
}
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string PropertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
private void Load_Executed(object sender, ExecutedRoutedEventArgs e)
{
FrameSource = e.Parameter.ToString();
}
private void Back_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (MainFrame != null && MainFrame.NavigationService != null)
e.CanExecute = (MainFrame.NavigationService.CanGoBack);
}
private void Back_Executed(object sender, ExecutedRoutedEventArgs e)
{
MainFrame.NavigationService.GoBack();
}
}
}
Note we move forward by setting the Frame's Source property via the binding but we navigate back by using the NavigationService's GoBack method.
Add a couple of trivial Page1.xaml and Page2.xaml pages. They have no code behind and the XAML for Page1 looks like this. You can figure out Page2 on your own.
<Page x:Class="GoBack.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:local="clr-namespace:GoBack">
<Grid>
<TextBlock Text="Page 1"/>
</Grid>
</Page>
Now click [Load Page 2] and note both the Frame's Source and its bound property both point to Page 2. Navigating by setting the bound property keeps them both in sync.
Now click [Go Backward]. Although you move to the correct page, note the bound property is still pointing to Page 2. If you navigate using the NavigationService the bound property does not get updated although the Frame's Source property is updated correctly.
Now change the Frame's XAML definition to explicitly set the binding mode to TwoWay like this.
<Frame Name="MainFrame" Grid.Row="3" Source="{Binding FrameSource, Mode=TwoWay}" Background="AliceBlue"/>
No comments:
Post a Comment