WPFらしいアプリケーションの例 1周遅れのWPF入門

マイクロソフト系プラットフォームでWinFormsからWPFに移行せなアカンなーとかWPFにしたら何が嬉しいの?なんてことを思ってる人たちに捧げるシリーズです。

今回はWPFで作ったら何が嬉しいのかを俺っち的に感じられる例を1つあげてみる。

Visual Studio 2013(VS2012でも変わらんと思う)
.NET Framework 4.0(企業戦士のデフォルトはWindows7な筈なので)

で仕上げていきます。まずはプロジェクトの作成から

で、スケルトンの出来上がり。

MainWindow.xamlが選択されてるはずなので、左側にツールボックスとドキュメントアウトラインを表示させます。

今回は理屈抜きで手順を並べていきます。習うより慣れよ。理解は後からついてくる。
ツールボックス上でコンボボックスをダブルクリックします。

そしたらウィンドウの左上にコンボボックスが配置されます。

左上すぎるんで、マウスでグリグリとマージンをとりましょう。(位置合わせ)

その時、Xamlのコードは↓こんな感じになってるはずです。

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="10,10,0,0"/>

    </Grid>
</Window>

同様にLabelを1つと

TextBoxを1つダブルクリックで配置します。

同じようにマウスでグリグリっと位置合わせして

こんな感じになる。

その時、Xamlのコードは↓こんな感じになってるはずです。

    <Grid>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="10,10,0,0"/>
        <Label Content="Label" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,52,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,56,0,0"/>

    </Grid>

同じ要領でLabelを3つ、TextBoxも3つにします。


その時、Xamlのコード↓

    <Grid>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="10,10,0,0"/>
        <Label Content="Label" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,52,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,56,0,0"/>
        <Label Content="Label" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,95,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,99,0,0"/>
        <Label Content="Label" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,137,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,141,0,0"/>

    </Grid>

で、LabelのラベルがLabelじゃ味気ないんで企業戦士らしいラベルに変えます。雰囲気が出るようにね。
上から、ID、名前、住所でどうでしょうか。
ウィンドウ上でLabelにカーソルを入れる(≒ゆっくりクリックする)とラベルの編集に入ります。


これはLabelタグのContent属性を書き換えるのと同じです。

    <Grid>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="10,10,0,0"/>
        <Label Content="ID" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,52,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,56,0,0"/>
        <Label Content="名前" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,95,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,99,0,0"/>
        <Label Content="住所" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,137,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,141,0,0"/>

    </Grid>

デザイン上での操作はいったん止めてC#のコードに向き合います。
ソリューションエクスプローラ(右側)のプロジェクトの上で右クリックして

Memberクラスを作ります。

出来たてはこんな感じ。
Member.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication2
{
    class Member
    {
    }
}

で、C#の良い感じのシンタックスを使ってプロパティを3つ作ります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication2
{
    class Member
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }
}

続いて、MainWindow.xaml.csを開きます。(MainWindow.xamlの画面でF7キーが早いかな?)
初期コードは↓こんな感じ
MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication2
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

サンプルデータを1つ作ります。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var member = new Member
            {
                Id = "1000",
                Name = "fuku518",
                Address = "大阪府"
            };
            this.DataContext = member;
        }
    }

ここで実行して、なんとなく期待通りの表示になったら超嬉しいけどもうちょっとだけやることがあります。
MainWindow.xamlに表示を切り替えてxamlと少しだけ向き合います。(Shift+F7で切り替わる)
TextBoxの定義は

<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Margin="69,56,0,0"/>

こんな感じになってると思うので、その中のText属性をそれぞれ
"TextBox"から"{Binding Id}"、"{Binding Name}"、"{Binding Address}"
結果↓こんな感じになります。

    <Grid>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="10,10,0,0"/>
        <Label Content="ID" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,52,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Id}" VerticalAlignment="Top" Width="120" Margin="69,56,0,0"/>
        <Label Content="名前" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,95,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Top" Width="120" Margin="69,99,0,0"/>
        <Label Content="住所" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,137,0,0"/>
        <TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Address}" VerticalAlignment="Top" Width="120" Margin="69,141,0,0"/>

    </Grid>

では実行してみましょう。

ま、普通ですね。

アプリケーション内部に持つデータを画面表示に使う部品(ウィンドウズで言えばコントロール)に値を設定することで表示するのでは無く、データの項目名(プロパティ名)とコントロールの表示内容を結び付けて(Bind)同期させる。
これがWPFを使う1番最初の動機たりえるメリット。内部データモデルとビューの同期。(ただし、一方通行)

全部書くから超長い。だけど、こういう情報が本当に必要な人にはそれぐらいわかるやん!って省略したところでハマったりしがちなんで可能な限り端から端まで記述してく。

長すぎるんで、今日はここまで。次はメンバー一覧の表示をします。