2020년 7월 5일 일요일

WPF - ListView, TreeView

ListView


 우리가 파일 탐색기에서 파일 목록들이 보통 ListView 로 구현되어 있음.
 List랑 거의 비슷한데, GridView 와 함께 쓰이는 것이 다른 점.

1
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvCust.ItemsSource);
cs

위처럼 ICollectionView 를 호출할 수 있어서 Sort, Group 가능함.
또한 ItemTemplate, GroupStyle 등을 이용해 List 처럼 똑같이 커스터마이즈도 가능함


 1. GridView


1
2
3
4
5
6
7
<ListView.View>
    <GridView>
        <GridViewColumn Header="성명" Width="50" DisplayMemberBinding="{Binding Name}"/>
        <GridViewColumn Header="나이" Width="50" DisplayMemberBinding="{Binding Age}"/>
        <GridViewColumn Header="이메일" Width="100"/>
    </GridView>
</ListView.View>
cs

 위에처럼 List 내부에 Column 별로 커스터마이즈가 가능함.


1
2
3
4
5
<GridViewColumn.CellTemplate>
    <DataTemplate>
        <TextBlock TextDecorations="Underline" Foreground="Blue" Text="{Binding Email}"/>
    </DataTemplate>
</GridViewColumn.CellTemplate>
cs

여기에도 물론 템플릿 적용할 수 있음.
데이터 템플릿은 바인딩을 사용하는 경우 거의 사용가능함.

1
2
3
<GridViewColumn.Header>
     <GridViewColumnHeader Tag="Name" Click="GridViewColumnHeader_Click" Content="이름"/>
</GridViewColumn.Header>
cs

Header 의 경우 위처럼 따로 커스터마이즈 가능함.
이때 Tag 는 Click 함수의 Sender 에서 GridViewColumnHeader 로 형변환시 얻을 수 있음.


 2. Column

1
listView.Items.SortDescriptions.Add(new SortDescription(h.Tag.ToString(), ListSortDirection.Ascending));
cs

listView 에는 Item 이 있는데, 이거 하나가 Column 하나를 대표함.




TreeView


 이런거 만들 때 쓰는거임.

1. 재귀적 템플릿

1
2
3
4
5
6
7
<TreeView x:Name="trvMenu1">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type local:MyMenuItem}" ItemsSource="{Binding Itemss}">
            <TextBlock Text="{Binding Title}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
cs

하나의 클래스로 재귀적으로 돌릴 때는 위처럼 함.
ItemTemplate 밑에 HierarchicalDataTemplate 을 넣는 거임.

이 경우 DataType 은 명시할 펼요 없지만, ItemsSource 는 명시해야함.
hierachicalDataTemplate 의 ItemSource 는 자기의 자식들을 나타냄.

List<MyMenuItemlst = new List<MyMenuItem>(){ r1r2r3 };
trvMenu1.ItemsSource = lst;

TreeView 의 ItemSource 가 처음 노드의 리스트라면, 그 리스트는 자기가 자신의 리스트를 가지고, 이것이 위의 템플릿의 ItemSource 와 바인딩이 되어야 한다는 것임. 

trvMenu1.Items.Add(r1);
trvMenu1.Items.Add(r2);
trvMenu1.Items.Add(r3);
위에건 이렇게 넣어도 상관 없음.

2. SubTree 업데이트

1
2
3
4
5
private void content_browser_treeview_Expanded(object sender, RoutedEventArgs e)
{
    TreeViewItem item = e.OriginalSource as TreeViewItem;
    item.ItemsSource = vm.Load_Content_Broswer_Disk_Items(((Content_Browser_Item)it
}
cs

위는 TreeView 의 TreeViewItem.Expanded 의 이벤트 핸들러임.
위처럼 TreeViewItem 의 ItemsSource 를 업데이트하는걸로 

3. 데이터별 템플릿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:Corp}" ItemsSource="{Binding Members}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" FontSize="16"/>
            <TextBlock Margin="10, 0, 0, 0">[</TextBlock>
            <TextBlock Text="{Binding Members.Count}" Foreground="Blue" FontSize="16"/>
            <TextBlock>]</TextBlock>
        </StackPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type local:Emp}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}"/>
            <TextBlock Margin="10, 0, 0, 0">(</TextBlock>
            <TextBlock Text="{Binding Age}" Foreground="Green"/>
            <TextBlock>)</TextBlock>
        </StackPanel>
    </HierarchicalDataTemplate>
</TreeView.Resources>
cs

resources 에 따로 옮겨서 DataType 과 일치하는 것이 바로 적용되도록 하게함.
물론 이건 Template 이므로 window 나 apps 의 resources 에 둬도 적용이 됨. 


4  펼치고 접기

1
2
3
4
5
6
<TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
        <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
        <Setter Property="IsExpanded" Value="{Binding IsExpanded}"/>
    </Style>
</TreeView.ItemContainerStyle>
cs

IsSelected 와 IsExpaneded 라는 속성이 각 Item 마다 있다.
위처럼 ItemContainerStyle 에서 이 값은 다른 값과 연동시키고, INotifyPropertyChanged 등을 이용하면 코드로도 열고 닫을 수 있게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class TreeViewItemBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void Notify(string propName)
    {
        if (PropertyChanged != null)
            this.PropertyChanged(thisnew PropertyChangedEventArgs(propName));
    }
 
    private bool isSelected;
    public bool IsSelected
    {
        get { return isSelected; }
        set { if (isSelected == value) return; isSelected = value; Notify("IsSelected"); }
    }
    private bool isExpanded;
    public bool IsExpanded
    {
        get { return isExpanded; }
        set { if (isExpanded == value) return; isExpanded = value; Notify("IsExpanded"); }
    }
}
 
class Corp : TreeViewItemBase
{
    public string Name { get; set; }
    public ObservableCollection<Emp> Members { get; set; }        
    public Corp()
    {
        Members = new ObservableCollection<Emp>();
    }
}
cs

이는 INotifiyPropertyChanged 를 이용한 것이다.



댓글 없음:

댓글 쓰기

List