'TreeView'에 해당되는 글 1건

  1. 2009.04.16 HierarchicalDataTemplate 활용

먼저 HierarchicalDataTemplate에 대한 MSDN 예제를 간단히 살펴보고 계층적으로 똑같은 도메인 객체를 바인딩할 경우와 TreeView의 성능에 대한 문제에 대해서 살펴보도록 하겠습니다.

아래는 MSDN에서 HierarchicalDataTemplate 예제입니다.
http://msdn.microsoft.com/ko-kr/library/ms771440.aspx

아래는 위의 예제를 실행시킨 화면과 소스입니다.

public class Division

{

    public Division(string name)

    {

        _name = name;

        _teams = new List<Team>();

 

    }

 

    string _name;

 

    public string Name { get { return _name; } }

 

    List<Team> _teams;

 

    public List<Team> Teams { get { return _teams; } }

 

}

<src:ListLeagueList x:Key="MyList"/>


<HierarchicalDataTemplate DataType    = "{x:Type src:League}"

                        ItemsSource = "{Binding Path=Divisions}">

<TextBlock Text="{Binding Path=Name}"/>

</HierarchicalDataTemplate>

 

<HierarchicalDataTemplate DataType    = "{x:Type src:Division}"

                        ItemsSource = "{Binding Path=Teams}">

<TextBlock Text="{Binding Path=Name}"/>

</HierarchicalDataTemplate>

 

<DataTemplate DataType="{x:Type src:Team}">

<TextBlock Text="{Binding Path=Name}"/>

</DataTemplate>

<TreeView>

  <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />

</TreeView>

 

=> 먼저 바인딩되는 객체는 XAML코드에 정의된 key MyList ListLeagueList : List<League> 타입의 객체입니다. 이중에서 Division 클래스와 Team 클래스의 관계를 살펴보면 1:N의 관계로 설정이 된 것을 볼 수 있고 이렇게 계층적으로 나타낼 수 있는 객체를 HierarchicalDataTemplate를 이용해서 바인딩 하는 것을 볼 수 있습니다.


그렇다면 동일 클래스를 계층적으로 나타내고 싶을 경우에 도메인 모델을 어떻게 설계해야 할까요? 처음에는 단순하게 도메인 모델을 여러개로 나눠서 계층적으로 설계를 하다가 계층이 많아지면 계속 그 만큼 만들어주어야 하는 비효율적이고 수동적인 느낌이 들었습니다. 그래서 그냥 심플하게 자신의 클래스 안에 List<>형태로 자신을 가지고 있으면 된다는 생각이 들었습니다. 저는 기초코드성 코드를 계층적으로 나타낼 경우에 아래와 같이 도메인 모델 클래스를 만들었습니다.
public class BaseCode

{

    public BaseCode(string name)

    {

        this.Name = name;

        SubList = new List<BaseCode>();

    }

 

    public string Name { get; set; }

 

    public List<BaseCode> SubList { get; set; }

}

<src:ListBaseCodeList x:Key="MyList"/>

 

<HierarchicalDataTemplate DataType    = "{x:Type src:BaseCode}"

                        ItemsSource = "{Binding Path=SubList}">

<TextBlock Text="{Binding Path=Name}"/>

</HierarchicalDataTemplate>

=>  BaseCode 클래스를 살펴보면 BaseCode 클래스 안의 프로퍼티로 List<>형태로 자신과 똑같은 클래스를 가지고 있습니다. 그러면 그 List<>안에 있는 클래스도 마찬가지로 List<>형태의 자신의 클래스를 가지고 있는 것처럼 계층적으로 도메인 모델을 나타낼 수 있습니다. 이어서 XAML코드를 살펴보면 HierarchicalDataTemplate를 하나만 해준 것을 볼 수 있습니다. 이것은 바로 DataType 프로퍼티의 힘으로 똑같은 데이터 타입을 계층적으로 표시해줍니다. 아래 화면은 실행화면입니다.


=> 여기서 몇 가지 생각해 볼 사항들이 있습니다. 자식 노드에서 부모 노드의 값을 알고 싶거나 TreeView에 바인딩 되는 데이터의 양이 너무 많을 경우 트리를 펼칠 경우에 자식의 자식 노드(펼치는 순간 자식 노드를 펼칠 수 있는지 없는지를 알아야하기 때문에)를 가져오는 방법 등입니다.

일반적으로 TreeView에 바인딩 되는 데이터를 가공(쿼리 결과 값등)하는 시간이 그렇게 오래 걸리지 않는다면 TreeView에 모든 데이터를 바인딩하고 TreeView에 성능을 개선하는 방법으로 해결하면 될 것이라 생각됩니다.
그럼 TreeView의 성능에 대한 문제점에 대해서 살펴보도록 하겠습니다.
표시할 데이터의 양이 많아지면 프로그램에 성능에 당연히 영향을 주게됩니다. 많은 데이터를 컨트롤에 바인딩 할 경우에는 그 항목을 표시해주기 위한 레이아웃 컨테이너를 만들고 해당 레이아웃의 크기와 위치를 계산하기 때문입니다. 이러한 성능과 관련된 요소를 크게 2가지로 나타낼 수 있습니다.
1. 컨테이너의 재활용
2. UI 가상화
컨테이너의 재활용은 위에서 말했던 레이아웃 컨테이너를 만들고 사라지는 과정 대신에 이미 한번 만들어진 컨테이너를 재활용을 하는 것을 말하며 UI가상화는 항목이 실제로 표시될 때까지는 해당 항목에 대한 항목 컨테이너 생성 및 연결된 레이아웃에 대한 계산을 지연시키는 것을 말합니다.

그럼 이 두가지를 사용한 예제는 MSDN에 있습니다. 단순히 프로퍼티를 설정해줌으로써 성능상의 얼마만큼의 영향을 주는지 직접 한번 실행해보시면 조금은 놀라실 수 있을 것입니다.
http://msdn.microsoft.com/ko-kr/library/cc716882.aspx

VirtualizingStackPanel.IsVirtualizing="True"

VirtualizingStackPanel.VirtualizationMode="Recycling"

=> 예제에서는 최상위 항목을 100개 그 항목마다 하위 항목을 10개를 가지고 있었는데 그렇게 큰 차이는 느껴지지 않아 최상위 항목을 1000개로 늘려보았더니 위의 프로퍼티를 지정해줄 경우에는 이전과 차이가 없었지만 위의 프로퍼티를 지정해주지 않을 경우에는 엄청나게 느린 것을 확실히 느낄 수 있었습니다.
Posted by resisa
,