앱에서 트리형태를 만들어야 한다면 어떻게 할 것인가?

우선 기본 컨트롤에는 트리 형태의 컨트롤이 없다.

이 때 부터 머리가 아파오기 시작한다. 자체적으로 만들어서 사용할 것인가..아니면 NuGet에서 찾아볼 것인가.. 3rd party 컨트롤을 이용해야 할 것인가.


이 중에 가장 현실적인 것은 WinRT Xaml Toolkit에 TreeView control을 사용하는 것으로, 윈도우 폰 8.1도 지원한다는 것이 큰 매력 포인트이다.








대략 위와 같은 느낌이다.


그런데, TreeView control을 사용하는데 약간 어려운 점이 있는데 ..........................




1. TreeViewSample


MainPage.xaml


<Page
    x:Class="TreeViewSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TreeViewSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="using:WinRTXamlToolkit.Controls"
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:data="using:WinRTXamlToolkit.Controls.Data"
    mc:Ignorable="d">

    <d:Page.DataContext>
        <local:MainPageVM/>
    </d:Page.DataContext>

    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="Loaded">
            <core:InvokeCommandAction Command="{Binding LoadedCommand}"/>
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>


    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="133*"/>
            <RowDefinition Height="520*"/>
            <RowDefinition Height="115*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="404*"/>
            <ColumnDefinition Width="557*"/>
            <ColumnDefinition Width="405*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.ColumnSpan="3" TextWrapping="Wrap" Text="TreeView Sample" Style="{StaticResource HeaderTextBlockStyle}" VerticalAlignment="Center" HorizontalAlignment="Center"/>

        <toolkit:TreeView Grid.Column="1" Grid.Row="1"
                          ItemsSource="{Binding TreeViewBindingList}"
                          BorderBrush="White" BorderThickness="1">
            <interactivity:Interaction.Behaviors>
                <core:EventTriggerBehavior EventName="SelectedItemChanged">
                    <core:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/>
                </core:EventTriggerBehavior>
            </interactivity:Interaction.Behaviors>
            <toolkit:TreeView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                    <data:DataTemplateExtensions.Hierarchy>
                        <data:HierarchicalDataTemplate ItemsSource="{Binding ValueObject}" />
                    </data:DataTemplateExtensions.Hierarchy>
                </DataTemplate>
            </toolkit:TreeView.ItemTemplate>
        </toolkit:TreeView>
    </Grid>
</Page>



MainPageVM.cs

}
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;

namespace TreeViewSample
{
    public class MainPageVM : BindableBase
    {
        private readonly IList<CommonM> _allItems = new List<CommonM>();
        private ICommand _loadedCommand;
        private ICommand _selectionChangedCommand;
        private IList<CommonM> _treeViewBindingList;

        public IList<CommonM> TreeViewBindingList
        {
            get { return _treeViewBindingList; }
            set { SetProperty(ref _treeViewBindingList, value); }
        }

        /// <summary>
        ///     셀렉션 체인지 커맨드
        /// </summary>
        public ICommand SelectionChangedCommand
        {
            get { return _selectionChangedCommand = _selectionChangedCommand ?? new DelegateCommand(obj => { }); }
        }

        public ICommand LoadedCommand
        {
            get
            {
                return _loadedCommand = _loadedCommand ?? new DelegateCommand(obj =>
                {
                    var subList = new List<CommonM>
                    {
                        new CommonM {Id = "01", Name = "Sub01"},
                        new CommonM {Id = "02", Name = "Sub02"},
                        new CommonM {Id = "03", Name = "Sub03"},
                        new CommonM {Id = "04", Name = "Sub04"},
                        new CommonM {Id = "05", Name = "Sub05"}
                    };
                    var add = (from kkk in subList
                        select AddItem((IList) _allItems, kkk)).Count();
                    var root = new CommonM {Id = "00", Name = "Root", ValueObject = subList};
                    AddItem((IList) _allItems, root);

                    TreeViewBindingList = new List<CommonM>
                    {
                        root
                    };
                });
            }
        }

        private bool AddItem(IList list, object item)
        {
            if (list.Contains(item)) return false;
            list.Add(item);
            return true;
        }
    }
}



실행해보자.





화면에 Root가 보이고, 왼쪽 삼각형 모양을 누르면 펼처져서 서브아이템들이 보이고, 다시 누르면 닫혀진다.


이제 사용상의 어려운 점을 이야기를 하면, 삼각형 모양을 눌러서 펼처지고, 닫혀지는 부분에 대한 이벤트가 존재하지 않다는 것이다. 이 부분에 이벤트가 없으니, 처음부터 모든 내용을 알고 있지 않다면, 중간에 아이템을 추가로 넣는 작업을 하기가 어렵다는 것이다.




그렇다면, 여기서 문제!!

어떻게하면, 맨위에 이미지처럼 펼처질 때 각 서브 아이템들의 서브를 구해서 넣을 수 있을까요?

직접 구현을 하시거나, 설명을 하시면 됩니다~



난이도 높음



지금까지의 소스

TreeViewSample.zip



블로그 이미지

kaki104

/// Microsoft MVP - Windows Development 2014 ~ 2019 5ring /// twitter : @kaki104, facebook : https://www.facebook.com/kaki104 https://www.facebook.com/groups/w10app/

티스토리 툴바