본문 바로가기
Windows/C#/WPF

데이터 바인딩 2

by hirudev 2021. 5. 11.

데이터 바인딩 1

https://hirudev.tistory.com/25


CollectionView

    public partial class MainWindow : Window
    {
        private ObservableCollection<Person> people;
        public MainWindow()
        {
            InitializeComponent();

            people = new ObservableCollection<Person>( Enumerable.Range(0,10).Select((e, ret)=> new Person
            {
                Name = string.Format("test{0}", e),
                Age = e
            }) );

            var v = CollectionViewSource.GetDefaultView(people);
            v.Filter = x => {
                var person = (Person)x;
                return person.Age % 2 == 0;
            };
            v.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Descending));

            this.listbox.DataContext = people;
        }
    }
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

↑ 필터, 정렬을 사용한 예

 

컬렉션 데이터 바인딩을 하면 내부적으로 직접 콜렉션이 바인딩되는 것이 아니고

 

사이에 CollectionView 라는 것이 암묵적으로 생성된다.

 

이 CollectionView 로 필터, 그룹화 처리가 가능하다.

 

    public partial class MainWindow : Window
    {
        class AgeConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return (int)value / 3;
            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
        private ObservableCollection<Person> people;
        public MainWindow()
        {
            InitializeComponent();

            people = new ObservableCollection<Person>( Enumerable.Range(0,10).Select((e, ret)=> new Person
            {
                Name = string.Format("test{0}", e),
                Age = e
            }) );

            var v = CollectionViewSource.GetDefaultView(people);
            v.GroupDescriptions.Add(new PropertyGroupDescription("Age", new AgeConverter()));

            this.listbox.DataContext = people;
        }
    }
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

 

        <ListBox x:Name="listbox" ItemsSource="{Binding}">
            <ListBox.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name, StringFormat={} {0}}" />
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListBox.GroupStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Name}"/>
                        <Label Content="{Binding Age}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>     

 

위 소스는 그룹화 시킨 예이다.

 

 

실시간 정렬 필터 그룹핑

프로퍼티 설명
IsLiveFilteringRequested true 시 아이템이 추가될 때마다 실시간으로 필터링됨.
IsLiveSortingRequested true 시 아이템이 추가될 때마다 실시간으로 정렬됨.
IsLiveGroupingRequested true 시 아이템이 추가될 때마다 실시간으로 그룹화됨.

 

// C# 코드 예제
            people = new ObservableCollection<Person>( Enumerable.Range(0,10).Select((e, ret)=> new Person
            {
                Name = string.Format("test{0}", e),
                Age = e
            }) );

            CollectionViewSource cvs = new CollectionViewSource();
            cvs.Source = people;
            cvs.IsLiveSortingRequested = true;
            cvs.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Descending));
            
            this.listbox.DataContext = cvs;

 

<!-- XAML 으로 작성했을 때의 예제 -->

<Window.Resources>
	<CollectionViewSource 
	    x:Key="Source" 
	    Source="{Binding}"  
	    IsLiveFilteringRequested="True"  
	    IsLiveGroupingRequested="True"  
	    IsLiveSortingRequested="True" > 
	    <CollectionViewSource.LiveSortingProperties> 
	        <System:String>Age</System:String> 
	    </CollectionViewSource.LiveSortingProperties> 
	    <CollectionViewSource.LiveGroupingProperties> 
	        <System:String>Age</System:String> 
	    </CollectionViewSource.LiveGroupingProperties> 
	    <CollectionViewSource.LiveFilteringProperties> 
	        <System:String>Age</System:String> 
	    </CollectionViewSource.LiveFilteringProperties> 
	</CollectionViewSource> 
</Window.Resources>

 

현재 선택항목을 바인딩하는 방법

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = new MainWindowViewModel
            {
                People = new ObservableCollection<Person>(Enumerable.Range(0, 10).Select(
                    x => new Person {
                        Name = string.Format("test {0}", x),
                        Age = x
                    }
                 ))
            };
        }
    }

    public class MainWindowViewModel
    {
        public ObservableCollection<Person> People { get; set; }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

 

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <DataGrid IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding People}" Grid.Column="0" Grid.Row="0" />
        <StackPanel Grid.Column="1">
            <TextBlock Text="Name" />
            <TextBox TextWrapping="Wrap" Text="{Binding People/Name}" />
            <TextBlock Text="Age" />
            <TextBox TextWrapping="Wrap" Text="{Binding People/Age}" />
        </StackPanel>
    </Grid>

 

다른 쓰레드에서 콜렉션 조작

        <DataGrid x:Name="datagrid" />

 

    public partial class MainWindow : Window
    {
        private ObservableCollection<Person> people;
        public MainWindow()
        {
            InitializeComponent();

            // Age 0 ~ 9 까지 데이터바인딩
            people = new ObservableCollection<Person>(Enumerable.Range(0, 10).Select(
                x => new Person
                {
                    Name = string.Format("test {0}", x),
                    Age = x
                }
             ));

            this.datagrid.ItemsSource = people;

            // 콜렉션 조작을 락을 할 수 있게 설정.
            BindingOperations.EnableCollectionSynchronization(people, new object());

            // 다른 쓰레드 생성 Age 10 ~ 19까지
            Task task = new Task(() =>
            {
                for (int i = 10; i < 20; i++)
                {
                    people.Add(new Person { Name = "test", Age = i });
                    Thread.Sleep(1000);
                }
            });
            task.Start();
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

 

 

'Windows > C#/WPF' 카테고리의 다른 글

[WPF] 나중에 참고할 링크  (0) 2021.05.12
커멘드  (0) 2021.05.12
데이터 바인딩 1  (0) 2021.05.09
리소스 & ControlTemplate  (0) 2021.05.08
스타일  (0) 2021.05.08

댓글