블로그 이미지
* Microsoft MVP - Windows Development 2014 ~ 2019 5ring * LINE : kaki104 * facebook : https://www.facebook.com/kaki104 https://www.facebook.com/groups/w10app/ kaki104

카테고리

List All (551)
Xamarin Forms (4)
Bot Framework (19)
Azure (9)
Windows 10 (35)
Facebook News & Tips (158)
Windows App(Universa.. (83)
Windows 8&8.1 (113)
Windows Phone 8 (42)
Silverlight (37)
HTML5 & MVC4 (16)
WPF (1)
Portable Class Library (2)
Uncategorised Tips a.. (3)
Kinect for Windows (2)
ETC (12)
kaki104 Scrap (4)
App News (11)
Total522,039
Today48
Yesterday101

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

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

이 때 부터 머리가 아파오기 시작한다. 자체적으로 만들어서 사용할 것인가..아니면 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



Posted by MVP kaki104

티스토리 툴바