技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

WPF を勉強してみるⅠ

今更だが、食わず嫌い(これまでちょこっと書いて動いたー程度)だったWPFを勉強しようと思った。
理由はコレ次期Visual Studio 2010と.NET Framework 4.0の新機能
やばい。かなりやばい。
Windows7 でも WPF は健在で、マルチタッチスクリーン対応だとぉぉぉおお!?
もう今からでも覚えねば危険だと思った。
実感できない人はコレを見れば一発で分かるというもの。
とりあえず、VisualStudio2008(自分はStandard)を起動し、

  1. 新しいプロジェクト
  2. Windows
  3. WPFアプリケーション

で作成。名前は適当(ここではWpfSample1)。

すると、xaml ファイルの編集が目の前に表示される。
GUI の表示イメージとその XML ファイルだ。
この時点で、XML を編集して見た目を弄るというのが(勘で)分かる。

他のファイルを見ると何があるかというと、

  • AssemblyInfo.cs
  • Resources.resx
  • Settings.settings
  • app.config
  • App.xaml
  • Window1.xaml

AssemblyInfo.cs はアセンブリ情報。別にWPF特有のものでもないので無視。
Resources.resx は中身見たところ、「名前、値、コメント」の項目があるだけ。特別な意味はなく、環境依存文字列(日本語メッセージとか)を格納しとくフィールドだろうと予想。コレ入れ替えることで外国語対応とかね。
Settings.settings を見ると、「名前、型、スコープ、値」の項目がある。おそらく文字通りアプリケーション内から読み取る設定ファイルなのだろう。型を見てみると、「System.Drawing.Color」とかあるから、UIの一部設定もできると見た。
app.config は別にWPF特有のモノではないかな。Setting にも近いけど、動作時に読み取られる設定ファイル。一応、利用するアセンブリのバージョンとか指定したりもできる。
App.xaml ぱっと見不明。調べたところ、アプリケーションのリソースと情報を記述できるらしい。
App.xaml.cs 同じくぱと見不明。アプリケーション全体のイベントを扱うのだそうだが、現時点では不明。
Window1.xaml 実際のアプリケーションUIの設定情報
Window1.xaml.cs アプリケーション処理の実態

とりあえずWindowフォームの基本。クリックカウントを入れてみる。


Window1.xaml を直接コード編集。やはりというか、コードニスペットは健在だったので、あんまこの位なら苦労しなかった。

<Window x:Class="WpfSample1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="114.534" Width="116.352">
    <Grid>
        <Button Margin="10,40,10,15" Name="buttonCount"
                Click="buttonCount_Click" Content="Click!" />
        <Label Height="23" Margin="5,5,5,10" Name="labelCount"
               VerticalAlignment="Top" Content="ClickCount"/>
    </Grid>
</Window>

このとき、Name アトリビュートを設定しないと、プログラムコード中でこれらコントロールのインスタンスにアクセスできなくてしんどいw
また、Click を作成するときに、Name を先に定義しとかないと、上手くイベントハンドラが製作できない模様(理由は後述)。

対応する Window1.xaml.cs はこんな感じ

public partial class Window1 : Window
{
    int value = 0;
    public Window1()
    {
        InitializeComponent();
        labelCount.Content = value.ToString();
    }

    private void buttonCount_Click(object sender, RoutedEventArgs e)
    {
        value++;
        labelCount.Content = value.ToString();
    }
}

これで実行すれば、カウントアップするプログラムが作られる。
ここで、気になる箇所がある。
「public partial class Window1 : Window」の1行だ。
「partial」ということは、Windowsフォームプログラム同様に、Designer.cs に該当するコードがどっかに自動生成されているはず!
ということで、それっぽい「InitializeComponent」を右クリック→「定義へ移動」する。するとアラ不思議。

public partial class Window1 : System.Windows.Window, System.Windows.Markup.IComponentConnector {

    #line 6 "..\..\Window1.xaml"
    internal System.Windows.Controls.Button buttonCount;

    #line default
    #line hidden

    /* 中略 */

    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
    void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
        switch (connectionId)
        {
        case 1:
        this.buttonCount = ((System.Windows.Controls.Button)(target));

        #line 6 "..\..\Window1.xaml"
        this.buttonCount.Click += new System.Windows.RoutedEventHandler(this.buttonCount_Click);

        #line default
        #line hidden
        return;
        case 2:
        this.labelCount = ((System.Windows.Controls.Label)(target));
        return;
        }
        this._contentLoaded = true;
    }
}

裏で自動生成してるのを隠してるのね、、、。
ここでイベントハンドラの登録とか行っているので、逆に言えば自動生成に頼らない場合は自力でコード書く必要が出ると、、、。
して、自動生成でイベントハンドラを用意する場合、先に Name を記述して、クラスインスタンスを自動生成コード内で利用可能にしとかないと、イベントハンドラが関連付けできないというワケね。
今日はこのくらい。