프로그래밍/WPF

[WPF] TreeView MVVM IsSelected & IsExpanded Binding

흔한티벳여우 2022. 8. 3. 17:10
반응형

일단 TreeView의 사용법을 한번 알아보자.

<TreeView>
  <TreeViewItem Header="Employee1">
    <TreeViewItem Header="Jesper"/>
    <TreeViewItem Header="Aaberg"/>
    <TreeViewItem Header="12345"/>
  </TreeViewItem>
 <TreeViewItem Header="Employee2">
    <TreeViewItem Header="Dominik"/>
    <TreeViewItem Header="Paiha"/>
    <TreeViewItem Header="98765"/>
  </TreeViewItem>
</TreeView>

위와 같이 xaml을 작성한다면 아래와 같이 나온다.

우리가 여기서 중점적으로 봐야하는것은 ComboBox에서 ComboBoxItem 마냥 TreeViewItem이라는 컨트롤이다.

 

https://docs.microsoft.com/ko-kr/dotnet/api/system.windows.controls.treeviewitem?view=windowsdesktop-6.0 

 

TreeViewItem 클래스 (System.Windows.Controls)

TreeView 컨트롤에 선택 가능한 항목을 구현합니다.

docs.microsoft.com

TreeViewItem 을 MS Docs에서 확인해보면 속성으로 IsExpanded, IsSelected, IsSelectionActive라는 속성이 있는것을 확인할 수 있다. 

이름에서 알 수 있듯이 해당 아이템을 펼치거나 선택하거나 포커스가 유지된 상태로 선택되어있거나 뭐 그런내용이다.

 

그럼 바인딩을 해보자.

일단 프로그램은 Prism 라이브러리를 사용하였다. 만약 Prism을 사용하지 않는다면 INotifyPropertyChanged 을 상속받아서 처리하면된다.

 

일단 ViewModel을 만들어준다.

class TreeViewModel : BindableBase
{
    private List<Team> _teams;
    public List<Team> Teams
    {
        get { return _teams; }
        set { SetProperty(ref _teams, value); }
    }
    public TreeViewModel()
    {
        Teams = new List<Team>();

        ObservableCollection<Person> group1 = new ObservableCollection<Person>();
        Person person1 = new Person { Name = "IU" };
        Person person2 = new Person { Name = "lina" };
        group1.Add(person1);
        group1.Add(person2);

        ObservableCollection<Person> group2 = new ObservableCollection<Person>();
        Person person3 = new Person { Name = "rain" };
        Person person4 = new Person { Name = "unkown" };
        group2.Add(person3);
        group2.Add(person4);

        Teams = new List<Team>();
        Teams.Add(new Team { Department = "One", People = group1, IsExpanded = true});
        Teams.Add(new Team { Department = "R&D", People = group2, IsExpanded = true });
    }
}

public class Team : TreeViewItemProperty
{
    public ObservableCollection<Person> People { get; set; } = new ObservableCollection<Person>();
    public string Department { get; set; }
}
public class Person : TreeViewItemProperty
{
    public string Name { get; set; }
    public string Rank { get; set; }
}    

public class TreeViewItemProperty : BindableBase
{
    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set { SetProperty(ref _isSelected, value); }
    }

    private bool _isExpanded;
    public bool IsExpanded
    {
        get { return _isExpanded; }
        set { SetProperty(ref _isExpanded, value); }
    }
}

 

Xaml 를 작성해보자.

<Grid>
    <TreeView ItemsSource="{Binding Teams, Mode=TwoWay}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding People}" DataType="{x:Type vm:Team}">
                <TextBlock Text="{Binding Department}"/>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate DataType="{x:Type vm:Person}">
                        <TextBlock Text="{Binding Name}"/>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <TreeView.ItemContainerStyle>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            </Style>
        </TreeView.ItemContainerStyle>
    </TreeView>
</Grid>

TreeViewItemProperty에 IsSelected와 IsExpanded를 상속받은 아이템들을 TreeView의 ItemSource에 바인딩 처리하고 ItemContainerStyle에 바인딩 처리하면 된다.

 

반응형