locked
画面遷移について教えてください。 RRS feed

  • 質問

  • Silverlight、VB2010でアプリケーションを作成しております。

    SilverlightのFrameコントロールを使って、以下の動作を行いたく考えております。

    ①MainPageにFrameを用意して、

    Frame1.source = Page1.xaml

    を表示させます。Page1.xamlにはボタンコントロール(btn1)があります。

    上記状態の際にbtn1を押下したときに、Frame1を画面遷移(Page2.xaml)させたいのですが

    うまく遷移させることができません。

    基本的な問題で大変申し訳ありませんが、どなたかご教授よろしくお願いいたします。

    2011年2月3日 2:32

回答

  • ご指摘の通り、Navigatedイベントは、Frameが切り替わった瞬間に発生するイベントです。

    FrameがNavigatedイベントを発行する
    MainPageのFrame1_NavigatedイベントハンドラでPage1のインスタンスを取得する。
    取得したPage1インスタンスのNavigatePage2Requestイベント(このイベントは自分で定義したイベント)にイベントハンドラを登録する。
    Page1のボタンが押されると、NavigatePage2Requestイベントが発行される。
    Page1_NavigatePage2RequestイベントハンドラでPage2に遷移する。
    という流れになります。長いですが、コードも載せておきます(C#で申し訳ないです)。
    MainPage.xaml
    <UserControl x:Class="NavigationSample.MainPage"
      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:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">
    
    
      <UserControl.Resources>
        <uriMapper:UriMapper x:Key="uriMapper">
          <uriMapper:UriMapping Uri="Page1" MappedUri="/Page1.xaml" />
          <uriMapper:UriMapping Uri="Page2" MappedUri="/Page2.xaml" />
        </uriMapper:UriMapper>
      </UserControl.Resources>
    
      <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <StackPanel Grid.Row="0" Orientation="Horizontal" Background="LightCyan">
          <HyperlinkButton x:Name="Page1Button" Content="Page1" NavigateUri="Page1" />
          <HyperlinkButton x:Name="Page2Button" Content="Page2" NavigateUri="Page2" />
        </StackPanel>
    
        <navigation:Frame x:Name="Frame" UriMapper="{StaticResource uriMapper}" Grid.Row="1" Background="LightYellow" />
      </Grid>
    </UserControl>
    
    MainPage.xaml.cs
    public partial class MainPage : UserControl
    {
      public MainPage()
      {
        InitializeComponent();
    
        this.Frame.Navigated += new NavigatedEventHandler(this.Frame_Navigated);
      }
    
      private void Frame_Navigated(object sender, NavigationEventArgs e)
      {
        var page1 = e.Content as Page1;
        if (page1 != null)
        {
          // 2度イベントハンドラが登録されないように、念のため一度イベントハンドラを抜いてから登録する。
          page1.NavigatePage2Request -= new EventHandler(this.Page1_NavigatePage2Request);
          page1.NavigatePage2Request += new EventHandler(this.Page1_NavigatePage2Request);
        }
      }
    
      private void Page1_NavigatePage2Request(object sender, EventArgs e)
      {
        // Page1のボタンが押されたとき、Page2に遷移する。
        this.Frame.Navigate(this.Page2Button.NavigateUri);
      }
    }
    
    Page1.xaml
    <navigation:Page x:Class="NavigationSample.Page1" 
          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"
          mc:Ignorable="d"
          xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
          d:DesignWidth="640" d:DesignHeight="480"
          Title="Page1 Page">
      <Grid x:Name="LayoutRoot">
        <Button x:Name="Page2NavigationButton" Content="Page2へ遷移"/>
      </Grid>
    </navigation:Page>
    
    
    Page1.xaml.cs
    public partial class Page1 : Page
    {
      public Page1()
      {
        InitializeComponent();
    
        this.Page2NavigationButton.Click += new RoutedEventHandler(this.Page2NavigationButton_Click);
      }
    
      /// <summary>Page2へ遷移する要求を発行する。</summary>
      public event EventHandler NavigatePage2Request;
    
      private void Page2NavigationButton_Click(object sender, RoutedEventArgs e)
      {
        if (this.NavigatePage2Request != null)
        {
          this.NavigatePage2Request(this, EventArgs.Empty);
        }
      }
    }
    
    Page2.xaml
    <navigation:Page x:Class="NavigationSample.Page2" 
          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"
          mc:Ignorable="d"
          xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
          d:DesignWidth="640" d:DesignHeight="480"
          Title="Page2 Page">
      <Grid x:Name="LayoutRoot">
        <TextBlock Text="Page2" FontSize="30"/>
      </Grid>
    </navigation:Page>
    
    




    • 回答としてマーク ohzeki 2011年2月3日 20:36
    2011年2月3日 13:55

すべての返信

  • こんにちは。

     

    Silverlight デベロッパーセンターにSilverlightのFrameを使用した画面遷移について良い情報が御座いますので参照されてみてはいかがでしょうか?

    10行でズバリ!![VB] Silverlight - 画面遷移

     

    とても分かり易く、UriMapperの使用方法もこれで学習できると思います。

    是非試してください!


    ★良い回答には回答済みマークを付けよう! kazuto Blog : http://blogs.wankuma.com/kzt/
    2011年2月3日 7:44
  • 子から親へ処理を依頼する方法はいつも悩まされますね。

    子のページ(ここではPage1クラス)にイベントを定義して親ページでそのイベントにイベントハンドラを刺したり、Mediator パターンで子ページから親ページに通知をしたりなどの方法があります。

    さらに手っ取り早い方法としましてはApp.xaml.csページで

    private void Application_Startup(object sender, StartupEventArgs e)
    {
      this.RootVisual = new MainPage();
    }
    
    

    と定義されていることを前提とすると、Page1.xaml.csで

    private void btn1_Click(object sender, RoutedEventArgs e)
    {
      // MainPageインスタンスを取り出す。
      MainPage mainPage = App.Current.RootVisual as MainPage;
    
      // MainPageにページを遷移する処理を依頼する。
    }
    

    と、書くことができます。

    子が親のインスタンスを直接いじるのはどうなのよ?という気もしますが、小さいアプリならばこれで十分ではないでしょうか。

    2011年2月3日 8:48
  • 回答ありがとうございます。

    ぜひ参考にさせていただきます。

     

    2011年2月3日 9:52
  • 将来的に、複数ページ(クラス)の切り替えの実装を行いたいと考えておりまして、

    先に教えていただいた、子ページのイベントに親ページのイベントハンドラを渡す方法を

    もう少し詳しくご教授いただけませんでしょうか?

    もしくは参考HPなどがございましたらお教え願えませんでしょうか?

     

    無知で大変申し訳ありませんがよろしくお願いいたします。

     

     

    2011年2月3日 10:23
  • FrameクラスのNavigatedイベントで子ページのインスタンスを取得する方法はどうでしょうか?

    private void Frame_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
    {
      var page1 = e.Content as Page1;
      if (page1 != null)
      {
        // 2度イベントハンドラが登録されないように、念のため一度イベントハンドラを抜いてから登録する。
        page1.NavigatePage2Request -= new EventHandler(this.Page1_NavigatePage2Request);
        page1.NavigatePage2Request += new EventHandler(this.Page1_NavigatePage2Request);
      }
    }
    

     

     

    2011年2月3日 11:00
  • ご回答ありがとうございます。

    度重なる質問で申し訳ありませんが、

    Frame1_Navigatedイベントは、Frameが切り替わった瞬間に発生する

    イベントと思ったのですが、違いますでしょうか?

    Frameの中のボタン押下イベント時に、親からフレームを切り替えるということはできませんでしょうか?

    私の知識不足でお手数おかけして大変申し訳ありません。

     

    2011年2月3日 11:56
  • ご指摘の通り、Navigatedイベントは、Frameが切り替わった瞬間に発生するイベントです。

    FrameがNavigatedイベントを発行する
    MainPageのFrame1_NavigatedイベントハンドラでPage1のインスタンスを取得する。
    取得したPage1インスタンスのNavigatePage2Requestイベント(このイベントは自分で定義したイベント)にイベントハンドラを登録する。
    Page1のボタンが押されると、NavigatePage2Requestイベントが発行される。
    Page1_NavigatePage2RequestイベントハンドラでPage2に遷移する。
    という流れになります。長いですが、コードも載せておきます(C#で申し訳ないです)。
    MainPage.xaml
    <UserControl x:Class="NavigationSample.MainPage"
      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:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">
    
    
      <UserControl.Resources>
        <uriMapper:UriMapper x:Key="uriMapper">
          <uriMapper:UriMapping Uri="Page1" MappedUri="/Page1.xaml" />
          <uriMapper:UriMapping Uri="Page2" MappedUri="/Page2.xaml" />
        </uriMapper:UriMapper>
      </UserControl.Resources>
    
      <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <StackPanel Grid.Row="0" Orientation="Horizontal" Background="LightCyan">
          <HyperlinkButton x:Name="Page1Button" Content="Page1" NavigateUri="Page1" />
          <HyperlinkButton x:Name="Page2Button" Content="Page2" NavigateUri="Page2" />
        </StackPanel>
    
        <navigation:Frame x:Name="Frame" UriMapper="{StaticResource uriMapper}" Grid.Row="1" Background="LightYellow" />
      </Grid>
    </UserControl>
    
    MainPage.xaml.cs
    public partial class MainPage : UserControl
    {
      public MainPage()
      {
        InitializeComponent();
    
        this.Frame.Navigated += new NavigatedEventHandler(this.Frame_Navigated);
      }
    
      private void Frame_Navigated(object sender, NavigationEventArgs e)
      {
        var page1 = e.Content as Page1;
        if (page1 != null)
        {
          // 2度イベントハンドラが登録されないように、念のため一度イベントハンドラを抜いてから登録する。
          page1.NavigatePage2Request -= new EventHandler(this.Page1_NavigatePage2Request);
          page1.NavigatePage2Request += new EventHandler(this.Page1_NavigatePage2Request);
        }
      }
    
      private void Page1_NavigatePage2Request(object sender, EventArgs e)
      {
        // Page1のボタンが押されたとき、Page2に遷移する。
        this.Frame.Navigate(this.Page2Button.NavigateUri);
      }
    }
    
    Page1.xaml
    <navigation:Page x:Class="NavigationSample.Page1" 
          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"
          mc:Ignorable="d"
          xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
          d:DesignWidth="640" d:DesignHeight="480"
          Title="Page1 Page">
      <Grid x:Name="LayoutRoot">
        <Button x:Name="Page2NavigationButton" Content="Page2へ遷移"/>
      </Grid>
    </navigation:Page>
    
    
    Page1.xaml.cs
    public partial class Page1 : Page
    {
      public Page1()
      {
        InitializeComponent();
    
        this.Page2NavigationButton.Click += new RoutedEventHandler(this.Page2NavigationButton_Click);
      }
    
      /// <summary>Page2へ遷移する要求を発行する。</summary>
      public event EventHandler NavigatePage2Request;
    
      private void Page2NavigationButton_Click(object sender, RoutedEventArgs e)
      {
        if (this.NavigatePage2Request != null)
        {
          this.NavigatePage2Request(this, EventArgs.Empty);
        }
      }
    }
    
    Page2.xaml
    <navigation:Page x:Class="NavigationSample.Page2" 
          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"
          mc:Ignorable="d"
          xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
          d:DesignWidth="640" d:DesignHeight="480"
          Title="Page2 Page">
      <Grid x:Name="LayoutRoot">
        <TextBlock Text="Page2" FontSize="30"/>
      </Grid>
    </navigation:Page>
    
    




    • 回答としてマーク ohzeki 2011年2月3日 20:36
    2011年2月3日 13:55
  • 解決することができました。

    丁寧にご指導いただきまして、本当にありがとうございます。

    2011年2月3日 20:36