WPFことはじめ
WPFをはじめてみた。
いくつかwpfの記事や書籍を見たのだが小さく始まるお手軽なチュートリアルが無くて、
わりと学習曲線が急に感じられる(抽象から入る説明が苦手w)。
どうやら、WPFはWindowsFormsのようにWin32apiをラップしたものでは無くてDirectXの上に再構築したGUIらしい。
調べていくとこれが意外とよさげで、現時点のWindowsのGUIではベストな選択のような気がしてきた。
その代わりに最初に飲み込むべき概念がちょっと多いようだ。
メモしながら整理することにした。
まずは、ツリービューから。
モデル(追加 -> 新規クラス -> 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_; } } // 省略 } }
ボタンを押すとノードが追加されるようになった。