かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Hello worldを読んでみよう

先日さくっと作成したHello worldですが、拍子抜けするくらいあっさり出来ました。
なんにせよとっかかりが簡単というのは素晴らしいですね。


ということで、Hello worldの内容をひも解いてみてみようと思います。

XAML

その前に、Windows phone 7のアプリケーションを構成する要素の中で重要なXAMLについて簡単に説明しておこうと思います。
Windows phone 7のアプリケーションの画面は、普通はXAMLと呼ばれるXMLベースの言語で書きます。何それ?魔法の言語?ということはなくて、シンプルに言うとC#とかのクラスを組み立てるための言語です。

例えばHogehoge.Personというクラスがある場合は、以下のようなXAMLを書くとPersonクラスのインスタンスを作るという意味になります。

<Person xmlns="clr-namespace:Hogehoge">
</Person>

XML名前空間C#名前空間(ここでは指定してないけどアセンブリも指定できる)を指定して、タグ名でクラス名を指定します。そして、PersonクラスのAgeプロパティに100という値をセットするようにすると以下のようになります。

<Person xmlns="clr-namespace:Hogehoge" Age="100">
</Person>

XMLの属性を使ってプロパティをセットできます。因みに、プロパティのセットは、以下のような書き方も準備されてます。

<Person xmlns="clr-namespace:Hogehoge">
  <Person.Age>
    100
  </Person.Age>
</Person>

タグ名をクラス名.プロパティ名とすることで、プロパティを指定することが出来るようになってます。この例だと、ただメンドクサクなってるだけですが、この書き方をすると、クラスのプロパティの値にクラスのインスタンスをセットするということが出来るようになります。こうすることで、複雑なクラスを組み立てることが出来るようになってます。

こんな、仕組みでWindows phone 7の画面を構成するためのクラスのインスタンスを組み立てることで画面を構成していきます。
上記のような仕組みでWindows phone 7の画面は作られているので、やろうと思えばXAMLじゃなくてC#とかのコードで画面の部品のクラスのインスタンスを作って画面を組み立てることも出来ます。

コードビハインド

次に、コードビハインドです。コードビハインドは、XAMLで組み立てた画面のイベントハンドラとかを書いたりします。XAMLとコードビハインドの紐づけは、x:Class="クラス名"という属性で行われています。こう書いておくと、最終的にはパーシャルクラスを使ってコンパイルの時に1つのクラスにまとめられます。

エントリポイント

さて、基本的な構成要素の説明は終わったので、Windows phone 7のアプリケーションのエントリポイントを見てみようと思います。
エントリポイントといってもMainメソッドが見えるところにあるわけではなくて、App.xamlというXAMLとApp.xaml.csという2つのファイルが目に見える所でのエントリポイントになります。ということで、さくっとコードを全部引用します。

App.xaml

<Application 
    x:Class="HelloWorldApplication.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">

    <!--Application Resources-->
    <Application.Resources>
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
        <!--Required object that handles lifetime events for the application-->
        <shell:PhoneApplicationService 
            Launching="Application_Launching" Closing="Application_Closing" 
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>

</Application>

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace HelloWorldApplication
{
    public partial class App : Application
    {
        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public PhoneApplicationFrame RootFrame { get; private set; }

        /// <summary>
        /// Constructor for the Application object.
        /// </summary>
        public App()
        {
            // Global handler for uncaught exceptions. 
            UnhandledException += Application_UnhandledException;

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode, 
                // which shows areas of a page that are being GPU accelerated with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;
            }

            // Standard Silverlight initialization
            InitializeComponent();

            // Phone-specific initialization
            InitializePhoneApplication();
        }

        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        #region Phone application initialization

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != RootFrame)
                RootVisual = RootFrame;

            // Remove this handler since it is no longer needed
            RootFrame.Navigated -= CompleteInitializePhoneApplication;
        }

        #endregion
    }
}

色々入り組んでますが、コンストラクタで初期化処理を呼び出して、PhoneApplicationFrameクラスのインスタンスを作ってCompleteInitializePhoneApplicationでRootVisualにセットしています。RootVisualは、画面に表示されるルート要素になります。

ここまで読んでわからないことが出てきました。最初に表示されるのはMainPage.xamlなんですが、こいつが何処で設定されているのかさっぱりわかりません・・・。
ということで、ここをちょっと追及するところから続きやれたらやってみようと思います。

ということで今日は以上!つづく*1

*1:というか知ってる人がいたら教えてください