きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

Silverlight 2 実務適用に向けてのサンプル(2)

普通にこういったモノを作って行くのであれば、本来であれば多分、アプリの機能設計をして、そのあとプレゼンテーション側とビジネスロジック側の設計をブレイクダウンしつつ、それぞれのIFの設計を詰めて……って感じで入る気もしますが、今回はSilverlight2での習作ということで、Silverlight側での前述の構成をどう実現するか、ということにまずは焦点を置いてやっていきます。機能設計に至っては、ログインしてそれっぽい画面が出ればよい、と言うレベルで今回はイイし(^^;



まず、Silverlightを読み込み後にログイン画面を表示させ、ログインがOKであれば別の画面を表示させる、というものを実現する手段について。
たとえば、WinFormのアプリであれば、同じような事をするためには、たぶん以下のようにするのが一般的ではないか、と思います。

//WinFormでログインダイアログ→メイン処理画面の流れのサンプル。
//Program.csに書くと思ってください。
[STAThread]
static void Main() 
{
    DialogResult ret;

    // Loginダイアログ。ログインOKならDialogResultにOKをセットして終了。
    using (LoginForm f1 = new LoginForm()){
        ret = f1.ShowDialog();
    }

    if (ret == DialogResult.OK)
        Application.Run(new MainForm()); // MainFormが業務のメイン処理画面。
}

しかし、Silvrelightの場合、RootVisualにユーザコントロールを指定するところから始まるので、全く同じ手法はとれそうにありません(たぶん)。

で、どうしたモノかと悩んだり調べたりしていたところ、大野さんが公開されている以下のWebCastを発見しました。
http://teched.jp/Silverlight/tabid/54/language/ja-JP/Default.aspx の『 #2: 複数のページを切り替える』


ということで、上記を参考にして*1、以下の手順で要件を実装していきましょう。

  • ログイン用のUserControlを作っておく(命名:LoginPage.xaml
  • ログイン後に表示するUserControlを作っておく(命名:MainPage.xaml
  • ベースとなるVisual要素を持たないUserControlを作っておく(命名:BasePage.xaml
  • 起動後のRootVisualをBasePage.xamlに設定
  • BasePage.xamlの初期表示ににLoginPage.xamlを表示
  • LoginPage.xamlでログイン成功したら、BasePage.xamlからMainPage.xamlを表示する

流れとしてはこんな感じ。

では、実際に上記の流れだけを実装していきます。

環境等

前回言い忘れていたのですが、今回の開発環境は、『Visual Studio 2008 Pro 日本語版 + Microsoft Silverlight Tools (RC0)日本語版』です。
RC0から無料のVislal Web Developer 2008 SP1でもIDEでの開発が可能になっていますが、若干画面構成等が違うところがあるかもしれないので、必要があれば適宜読み替えてください。
なお2008年10月18日現在、Expression Blendの環境がちょっと微妙なことになっているっぽい*2ので、今回はBlendは使わない方向で行きます。なので、Visualはショボショボです(ぉ。

1.ソリューションを新規作成

プロジェクトの新規作成から、[Silverlight]-[Silverlightアプリケーション]を選択します。VWDの場合は、プロジェクトの新規作成から行ってください。サイトの新規作成からだと、Siverlightアプリケーションのテンプレートが選択できないはずです*3

また、ホストするWebアプリケーションの作成ダイアログで、Webアプリケーションプロジェクトを追加します。RC0からは既定でWebアプリケーションプロジェクトになってるので、たぶん、既定のままでいいです。
※「Webサイト」は選ばないように。

2.必要なUserControlを追加

必要なコントロールを追加します。(BasePage.xaml、LoginPage.xaml、MainPage.xaml

また、既定のPage.xamlは使わないので消しておきましょう。

3.とりあえず動くようにしてみる

細かいところはともかく、先に書いたとおり、ログイン画面→メイン画面の動きだけを動かしてみます。

App.xaml.csの編集

今のままだと、既定のPage.xamlを消したこともあってエラーが出てると思うので、Application_Startup内でRootVisualのところをBasePageのインスタンスをセットするように変えておきます。

//App.xaml.csprivate void Application_Startup(object sender, StartupEventArgs e)
        {
            this.RootVisual = new BasePage();
        }
〜
BasePage.xamlの編集

BasePage.xamlはビジュアル要素を持たないようにしたいので、LayoutRootのGrid要素をマルっと消してしまいます。編集後はいかのような感じ。

<UserControl x:Class="SL_BizAppSample.BasePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
</UserControl>
BasePage.xaml.csの編集

ここが一つの肝だとおもいます。やることは、

  1. 初期表示時に、ContentにLoginPageのインスタンスを設定してLoginPageを表示してやる。
  2. ContentをMainPageに切り替える処理を行うパブリックメソッドを定義しておく。

の二つ。

    public partial class BasePage : UserControl
    {
        public BasePage()
        {
            InitializeComponent();

            // 初回起動時はログイン画面を表示する。
            if (this.Content == null)
            {
                this.Content = new LoginPage();
            }
        }

        /// <summary>
        /// MainPageを表示する
        /// </summary>
        /// <remarks>
        /// LoginPageから呼ばれて、ContentをMainPageに切り替える
        /// </remarks>
        public void ShowMainPage()
        {
            this.Content = new MainPage();
        }
    }
LoginPage.xamlの編集

本来はTextBox等ログイン操作に必要なコントロールを置きますが、とりあえず画面切り替えの確認ということで、ButtonとTextBlockだけ置いておきます。(個人的になところですがExpressionが無いとGridだと使いにくい気がしてる人だったりするので、LayoutRootはCanvasにしてあります。お好みでやってください。)

<UserControl x:Class="SL_BizAppSample.LoginPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Canvas x:Name="LayoutRoot" Background="Azure">
        <TextBlock Canvas.Left="10" Canvas.Top="5">ログイン画面</TextBlock>
        <Button Canvas.Left="10" Canvas.Top="40" Content="ログイン" Click="Button_Click"></Button>
    </Canvas>
</UserControl>
LoginPage.xaml.csの編集

ログイン処理の実装……は後回しにして、ログインが成功したとしてページを切り替える処理を実装しておきます。
コードは見ての通り、ParentであるBasePageに作ったShowMainPageメソッドを呼び出すだけです。(蛇足な説明をしておくと、ParentをBasePageにキャストしてShowMainPageメソッドをコールするだけ)
これが、肝、その2でしょうか。

    public partial class LoginPage : UserControl
    {
        public LoginPage()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // ここでログイン処理を実装
            //ToDo:後で。

            // とりあえず、ログインが成功したとする。
            ((BasePage)Parent).ShowMainPage();
        }
    }
MainPage.xamlの編集

ここには、とりあえずMainPageに切り替わったことがわかるように文字を表示しておくだけの記述をしておきます。

<UserControl x:Class="SL_BizAppSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Canvas x:Name="LayoutRoot" Background="Azure">
        <TextBlock Canvas.Left="10" Canvas.Top="5">メイン画面</TextBlock>
    </Canvas>
</UserControl>

4.とりあえず実行

以上で、とりあえずこのフェーズでの実装は完了。実行してみると、以下のような感じになって、ログイン画面でボタンを押すと、メイン画面に切り替わる動きになったと思います。



今回は、とりあえずここまで。

*1:丸パクリって言うな〜!(笑

*2:Silverlight2の正式対応がBlend 2.5 Preview からExpression Blend2 SP1に移行しているのですが、SP1は現在英語版しか出てないので、日本語版のBlend2では使えない。また、2.5のPreviewが入っているとSilverlight ToolsのRCは入れられない。

*3:たぶん、Silverlight 1.0のコントロールのテンプレートしか出ない気がする