WPFことはじめ

WPFをはじめてみた。
いくつかwpfの記事や書籍を見たのだが小さく始まるお手軽なチュートリアルが無くて、
わりと学習曲線が急に感じられる(抽象から入る説明が苦手w)。
どうやら、WPFはWindowsFormsのようにWin32apiをラップしたものでは無くてDirectXの上に再構築したGUIらしい。
調べていくとこれが意外とよさげで、現時点のWindowsGUIではベストな選択のような気がしてきた。
その代わりに最初に飲み込むべき概念がちょっと多いようだ。
メモしながら整理することにした。


まずは、ツリービューから。


モデル(追加 -> 新規クラス -> Node.cs)

namespace Sample
{
    class Node
    {
        // プロパティじゃないとBindingできない
        private List<Node> children_ = new List<Node>();
        public List<Node> Children
        {
            get { return children_; }
        }

        // プロパティじゃないとBindingできない
        public string Name
        {
            get;
            set;
        }

        public Node(string name)
        {
            Name = name;
        }

        public Node AddChild(Node node)
        {
            children_.Add(node);
            return node;
        }
    }
}

ビュー(MainWindow.xaml)

<Window x:Class="Sample.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>
        <TreeView Width="200" Height="200" ItemsSource="{Binding Path=Children}"><!-- DataContext.Childrenの意らしい -->
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}"><!-- 再帰的。ChildrenのChildren  -->
                    <TextBlock Text="{Binding Path=Name}"/><!-- ノード一個分。Node.Name -->
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

ビューがモデルを参照する(MainWindow.xaml.cs)

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

            var tree=new Node("root");
            var node1=tree.AddChild(new Node("node1"));
            var node1_1 = node1.AddChild(new Node("node1_1"));
            var node1_2 = node1.AddChild(new Node("node1_2"));

            // ビューはDataContextを通してBindingする
            DataContext = tree;
        }
    }
}

実行してみた。"root"より下の階層が表示された。
rootのChildrenのChildrenから表示される。

モデルの更新通知を導入する

まず、モデルを更新するボタンを追加する

        <Button Height="23" HorizontalAlignment="Left" Margin="152,262,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">
            AddNode
        </Button>
namespace Sample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private Node root_;

        public MainWindow()
        {
            InitializeComponent();

            // 変更できるようにメンバ変数にとっておく
            root_=new Node("root");
            var node1=root_.AddChild(new Node("node1"));
            var node1_1 = node1.AddChild(new Node("node1_1"));
            var node1_2 = node1.AddChild(new Node("node1_2"));

            DataContext = root_;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // モデルを更新
            root_.AddChild(new Node("AddNode"));
        }
    }
}

ボタンを押しても画面は変化しない。

ListをObservableCollectionに置換する。

using System.Collections.ObjectModel;

namespace Sample
{
    class Node
    {
        // プロパティじゃないとBindingできない
        private ObservableCollection<Node> children_ = new ObservableCollection<Node>();
        public ObservableCollection<Node> Children
        {
            get { return children_; }
        }

// 省略

     }
}

ボタンを押すとノードが追加されるようになった。