ViewMakerで生成するWPF/Silverlightコントロール(16)TreeView編

今回は業務アプリとしては使用回数は多くありませんが、たまに出てくるTreeViewです。階層構造のあるオブジェクトを簡単にナビゲーションできるのでツール作成などでは重宝します。

TreeViewコントロール

TreeViewはWPF/Silverlightで若干機能差があります。ViewMakerでもWPF/Silverlightで使える項目が少し違います。Silverlightでは現在選択されているアイテムを保持するプロパティをバインドできるビヘイビアを追加開発して利用しています。WPFは標準で用意されたものを利用しています。コマンドはSelectedItemChangedのタイミング動作するものを用意しました。

    1. ItemsSource(一覧用のデータソース)
    2. DisplayMember(ItemsSourceの各アイテムの表示に利用するプロパティのパス)
    3. IsSelected(ItemsSourceの各アイテムの選択中かを示すプロパティのパス(Wpf))
    4. IsExpanded(ItemsSourceの各アイテムを展開するかを示すプロパティのパス(Wpf))
    5. SelectedObject(ItemsSourceの選択中のアイテムを保持するプロパティのパス(Silverlight))
    6. SelectedItemChanged(選択データ変更時に実行するコマンド)

WPFサンプルイメージとXAMLコード

<TreeView Name="TreeItemList" ItemsSource="{Binding Path=TreeItemList,Mode=OneWay}" 
	vg:TreeViewSelectedItemChangedBehavior.Command="{Binding Path=SelectedItemChangedCommand, Mode=OneWay}" 
	VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" 
	xmlns:vg="clr-namespace:ViewMaker.Core.Wpf;assembly=ViewMaker.Core">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Children,Mode=OneWay}">
            <TextBlock Text="{Binding Path=Name,Mode=OneWay}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

SilverlightサンプルイメージとXAMLコード

<sdk:TreeView Name="TreeItemList" ItemsSource="{Binding Path=TreeItemList,Mode=OneWay}" VerticalAlignment="Stretch" 
	HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
    <sdk:TreeView.ItemTemplate>
        <sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Children,Mode=OneWay}">
            <TextBlock Text="{Binding Path=Name,Mode=OneWay}" />
        </sdk:HierarchicalDataTemplate>
    </sdk:TreeView.ItemTemplate>
    <i:Interaction.Behaviors>
        <vg:TreeViewItemBehavior vg:SelectedObject="{Binding Path=SelectedTreeViewNode, Mode=TwoWay}" 
	xmlns:vg="clr-namespace:ViewMaker.Core.Silverlight;assembly=SilverlightViewMaker.Core" />
        <vg:TreeViewSelectedItemChangedBehavior vg:Command="{Binding Path=SelectedItemChangedCommand, Mode=OneWay}" 
	xmlns:vg="clr-namespace:ViewMaker.Core.Silverlight;assembly=SilverlightViewMaker.Core" />
    </i:Interaction.Behaviors>
</sdk:TreeView>

ViewModelコード

[View(ViewControlType.Grid)]
[ViewProperty("MinHeight", 150)]
public class TreeViewSample : ViewModel
{
    public class TreeViewNode : ViewModel
    {
        public string Name { get; set; }

        public bool IsSelected
        {
            get { return _isSelected; }
            set { _isSelected = value; OnPropertyChanged("IsSelected"); }
        }
        private bool _isSelected;


        public ObservableCollection<TreeViewNode> Children
        {
            get
            {
                if (_children == null)
                {
                    _children = new ObservableCollection<TreeViewNode>();
                    for (int i = 0; i < 5; i++)
                    {
                        _children.Add(new TreeViewNode { Name = "Data" + (cnt++).ToString() });
                    }
                }
                return _children;
            }
        }
        private ObservableCollection<TreeViewNode> _children;
        private static int cnt = 0;

        public TreeViewNode GetSelectedNode()
        {
            if (IsSelected) return this;
            foreach (var child in Children)
            {
                var node = child.GetSelectedNode();
                if (node != null) return node;
            }
            return null;
        }
    }

    public string SelectedName { get; set; }

    [View(ViewControlType.TreeView)]
    [ViewProperty(TreeViewControl.Properties.ItemsSource, "Children")]
    [ViewProperty(TreeViewControl.Properties.DisplayMember, "Name")]
    [ViewProperty(TreeViewControl.Properties.IsSelected, "IsSelected")]
    [ViewProperty(TreeViewControl.Properties.SelectedObject, "SelectedTreeViewNode")]
    [ViewProperty(TreeViewControl.Properties.SelectedItemChangedCommand, "SelectedItemChangedCommand")]
    public ObservableCollection<TreeViewNode> TreeItemList { get; set; }

    [Browsable(true)]
    public TreeViewNode SelectedTreeViewNode
    {
        get { return _selectedTreeViewNode; }
        set
        {
            _selectedTreeViewNode = value;
            OnPropertyChanged("SelectedTreeViewNode");
#if SILVERLIGHT
            _selectedTreeViewNode.IsSelected = true;
#endif
        }
    }
    private TreeViewNode _selectedTreeViewNode;


    [Browsable(false)]
    public ICommand SelectedItemChangedCommand { get { return CreateCommand(SelectedItemChanged); } }
    public void SelectedItemChanged(object item)
    {

        var treeNode = item as TreeViewNode;
        if (treeNode != null)
        {
            SelectedName = treeNode.Name;
            OnPropertyChanged("SelectedName");
#if !SILVERLIGHT
            SelectedTreeViewNode = treeNode;
#endif
        }
    }

    public TreeViewSample()
    {
        TreeItemList = new ObservableCollection<TreeViewNode>();
        TreeItemList.Add(new TreeViewNode { Name = "Root Node" });
    }
}