1. 데이터 컨테이너
데이터를 보관할 때 List<> 나 ObservableCollection<> 등을 사용할 수 있음.
후자는 INotifyPropertyChanged 참조하는 곳에 자동으로 호출되서 잘 쓰임.
private ICollectionView GetList() { CustList list = (CustList)this.FindResource("custList"); return CollectionViewSource.GetDefaultView(list); }
데이터 컨테이너는 ICollectionView 를 위처럼 얻을 수 있다.
이건 다양한 기능을 할 수 있다.
1. 현재 선택한 데이터
private void btnPre_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetList(); view.MoveCurrentToPrevious(); if (view.IsCurrentBeforeFirst) view.MoveCurrentToFirst(); } private void btnNext_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetList(); view.MoveCurrentToNext(); if (view.IsCurrentAfterLast) view.MoveCurrentToLast(); }
위처럼 현재 선택된 데이터를 조절할 수 있다.
이는 List, ComboBox 등에서의 Focus 와 자동으로 연동된다.
2. 정렬
private void btnSortAge_Click(object sender, RoutedEventArgs e) { ICollectionView list = GetList(); if (list.SortDescriptions.Count == 0) { list.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Descending)); list.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); } else { list.SortDescriptions.Clear(); } }
ICollectionView 는 다음과 같이 정렬시킬 수 있음.
인덱스가 작을 수록 우선도 높은 정렬이 됨.
private void btnSortName_Click(object sender, RoutedEventArgs e) { ListCollectionView list = (ListCollectionView)GetList(); if(list.CustomSort == null) { list.CustomSort = new CustSorter(); } else { list.CustomSort = null; } }
List 의 경우 ListCollectionView 를 사용해서 정렬을 커스터마이즈 할 수 있음.
이건 ICollectionView 를 상속하는 클래스임.
양수일 때 바꾼단 말임.
3. 필터링
private void btnFilter_Click(object sender, RoutedEventArgs e) { ICollectionView list = GetList(); if (list.Filter == null) { list.Filter = delegate (object item) { return ((Cust)item).Age >= 20; }; } else list.Filter = null; }
ICollectionView 에는 Filter 가 있어서 함수 오버라이딩으로 해결.
4. 그룹핑
private void btnGroupName_Click(object sender, RoutedEventArgs e) { ICollectionView list = GetList(); if (list.GroupDescriptions.Count == 0) list.GroupDescriptions.Add(new PropertyGroupDescription("Name")); else list.GroupDescriptions.Clear(); }
ICollectionView 에는 GroupDescriptions 가 있어서 여기에 위처럼 추가.
더해진 만큼 Tree 처럼 계층화가 됨.
private void btnGroupAge_Click(object sender, RoutedEventArgs e) { ICollectionView list = GetList(); if (list.GroupDescriptions.Count == 0) list.GroupDescriptions.Add( new PropertyGroupDescription("Age", new AgeToRangeConverter())); else list.GroupDescriptions.Clear(); }
전 글에서 설명한 IValueConverter 를 이용해 위처럼 그룹별 커스터마이즈
2. ListBox
<ListBox x:Name="lstCust" Grid.Column="0" ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValuePath="Age" IsSynchronizedWithCurrentItem="True" MouseDoubleClick="lstCust_MouseDoubleClick" />
여기서 리소스는 Item 자료형의 ToString 이라는 함수를 통해 변환되어 가져옴.
그러므로 ToString 함수를 오버라이드하면 잘 안쓰이지만 커스터마이즈 가능.
ItemSource 는 DataContext 랑 다른 자기가 사용할 데이터을 말함.
DisplayMember 와 SelectedItem, SelectedValue 가 중요함.
DisplayMember 로는 화면에 무엇이 보여지는지 설정 가능함.
SelectedValue 와 SelectedItem 은 구분되어
SelectedValuePath 은 위처럼 Item 중 원하는 속성만 정할 수 있음.
3. ComboBox
<ComboBox Grid.Row="6" Grid.Column="1" ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValuePath="Age" SelectedValue="{Binding Path=Age}" IsSynchronizedWithCurrentItem="True"/>
ListBox 랑 사용법이 거의 같음.
4. List Customize
1. ItemTemplate
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 | <ListBox.ItemTemplate> <DataTemplate DataType="{x:Type local:Cust}"> <Grid HorizontalAlignment="Stretch" Background="AliceBlue"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Source ="https://ww.namu.la/s/a5947ceb0c55cb5eefcb5370f5a39e7" Width="100" Height="50"/> <TextBlock Grid.Row="0" Grid.Column="1" Text="성명 : "/> <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Path=name}" /> <TextBlock Grid.Row="1" Grid.Column="1" Text="나이 : " /> <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding Path=age}" /> <Button x:Name="btnDelete" Grid.Row="0" Grid.Column="3" Content="삭제" Click="btnDelete_Click"/> <Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" VerticalAlignment="Bottom" BorderBrush="Black" BorderThickness="0, 0, 0, 1"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> | cs |
List 에서 아이템을 표현하는 형식을 지정 가능함.
DataTemplate 은 여러군데에서도 쓰임.
그래서 적용할 데이터 타입만 위처럼 지정하고, 윈도우의 Resource 등으로 빼도 적용됨.
해당 타입은 다 자동으로 쓰이는 것. 하지만 자주 쓰이진 않음.
보통은 List.ItemTemplate 에서 DataTemplate 을 Content 로 넣는 걸로 많이 사용함.
2. GroupStyle
1 2 3 | <ListBox.GroupStyle> <x:Static Member="GroupStyle.Default"/> </ListBox.GroupStyle> | cs |
위를 통해 그룹별로 UI 에 표시 가능.
이건 디폴트 적용
3. GroupStyle.HeaderTemplate
1 2 3 4 5 6 7 8 9 10 11 12 | <ListBox.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock Background="#333" Foreground="#ffffff" FontWeight="Bold"> <TextBlock Text="{Binding Name}"/> (<TextBlock Text="{Binding ItemCount}"/>) </TextBlock> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListBox.GroupStyle> | cs |
이렇게 그룹 헤더 커스터마이즈 가능함.
얘도 DataTemplate 처럼 Resource 로 옮기기도 가능함
4. GroupStyle.ContainerStyle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Expander IsExpanded="True"> <Expander.Header> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="#333" FontFamily="16"/> <TextBlock Text="{Binding ItemCount}" FontWeight="Bold" Foreground="#333" FontFamily="16" Margin="10,0,0,0"/> </StackPanel> </Expander.Header> <ItemsPresenter/> </Expander> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> | cs |
이거는 HeaderTemplate 과 다르게 클릭을 통해 접는 것도 가능함.
이는 위 코드대로 하면 되는데, 복잡해서 복붙하면서 쓸듯.
댓글 없음:
댓글 쓰기