CollectionView 는 필터를 적용할수 있습니다.

bool 값을 반환하는 메서드를 만들어 Filter 에 적용시키면됩니다.

 

bool 값을 반환하는 메서드를 아래 처럼 정의하고

* "K" 로 시작하는 값만 필터링하게 합니다.

 

        bool NameFilter(object obj)

        {

            return (obj as Person).Name.StartsWith

            (

                "K",

                StringComparison.CurrentCultureIgnoreCase

            );

        }

 

CollectionView 의 Filter = NameFilter; 로 적용하면 됩니다.

 

아래는 예시 코드입니다.

 

Person.cs

using System.ComponentModel;

 

namespace WpfApp

{

    public class Person : INotifyPropertyChanged

    {

        /// <summary>

        /// 속성변경 이벤트입니다.

        /// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        string name = "";

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        string nickName = "";

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        public string Name

        {

            set

            {

                this.name = value;

                OnPropertyChanged(nameof(Name));

            }

            get { return name; }

        }

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        public string NickName

        {

            set

            {

                nickName = value;

                OnPropertyChanged(nameof(NickName));

            }

            get { return nickName; }

        }

 

        /// <summary>

        /// 속성 값이 변경될 때 발생합니다.

        /// </summary>

        /// <param name="propertyName"></param>

        protected virtual void OnPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

}

 

 

MainWindow.xaml

<Window x:Class="WpfApp3.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="400">

    <StackPanel>

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10">

            <TextBox Name="searchTextBox" Text="" Width="200" VerticalContentAlignment="Center"/>

            <Button Name="searchButton" Content="Search" Padding="5" Margin="5" Click="searchButton_Click"/>

        </StackPanel>

        <TextBox

            Margin="12" Height="50" VerticalContentAlignment="Center"

            Text="{Binding Name,

                   Mode=TwoWay,

                   UpdateSourceTrigger=PropertyChanged}" />

        <TextBox

            Margin="12" Height="50" VerticalContentAlignment="Center"

            Text="{Binding NickName,

                   Mode=TwoWay,

                   UpdateSourceTrigger=PropertyChanged}" />

        

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">

            <Button Name="prevButton" Content="Prev" Padding="10" Margin="10" Click="prevButton_Click"/>

            <Button Name="nextButton" Content="Next" Padding="10" Margin="10" Click="nextButton_Click"/>

        </StackPanel>

    </StackPanel>

</Window>

 

 

MainWindow.xaml.cs

using System;

using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Linq;

using System.Windows;

using System.Windows.Data;

 

namespace WpfApp3

{

    public partial class MainWindow : Window

    {

        /// <summary>

        /// 데이터 collectionView 입니다.

        /// </summary>

        ICollectionView collectionView;

 

        public MainWindow()

        {

            InitializeComponent();

 

            ObservableCollection<Person> datas = new ObservableCollection<Person>();

 

            datas.Add(new Person() { Name = "Kang",  NickName = "Super" });

            datas.Add(new Person() { Name = "An",    NickName = "Father" });

            datas.Add(new Person() { Name = "Jang",  NickName = "Marvel" });

            datas.Add(new Person() { Name = "Joo",   NickName = "Mother" });

            datas.Add(new Person() { Name = "Kim",   NickName = "DC" });

 

            this.collectionView = CollectionViewSource.GetDefaultView(datas);

            this.collectionView.Filter = NameFilter;

            this.collectionView.CurrentChanged += CollectionView_CurrentChanged; ;

 

            this.collectionView.SortDescriptions.Add(new SortDescription(nameof(Person.Name), ListSortDirection.Ascending));

 

            this.DataContext = this.collectionView;

 

            // 처음값으로 이동시킵니다.

            this.collectionView.MoveCurrentToFirst();

        }

 

        /// <summary>

        /// 이전 값으로 이동하는 버튼 클릭이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void prevButton_Click(object sender, RoutedEventArgs e)

        {

            this.collectionView.MoveCurrentToPrevious();

        }

 

        /// <summary>

        /// 다음 값으로 이동하는 버튼 클릭이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void nextButton_Click(object sender, RoutedEventArgs e)

        {

            this.collectionView.MoveCurrentToNext();

        }

 

        /// <summary>

        /// CollectionView 현재값이 변경되었을때 발생되는 이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="args"></param>

        private void CollectionView_CurrentChanged(object sender, EventArgs e)

        {

            // 이전/다음 항목 존재여부에 따라 이전/다음 버튼을 활성화하거나 비활성화 합니다.

            this.prevButton.IsEnabled = this.collectionView.CurrentPosition > 0;

            this.nextButton.IsEnabled = this.collectionView.CurrentPosition < this.collectionView.Cast<object>().Count() - 1;

        }

 

        /// <summary>

        /// Search 버튼 클릭이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void searchButton_Click(object sender, RoutedEventArgs e)

        {

            // Refresh 하여 필터 적용된 내용이 보이도록합니다.

            this.collectionView.Refresh();

        }

 

        /// <summary>

        /// 이름 기준 필터입니다.

        /// </summary>

        /// <param name="obj"></param>

        /// <returns></returns>

        bool NameFilter(object obj)

        {

            return (obj as Person).Name.StartsWith

            (

                this.searchTextBox.Text,

                StringComparison.CurrentCultureIgnoreCase

            );

        }

    }

}

 

 

결과


결과를 보면 내용중에 필터링 된 내용만 볼수있도록 처리가 됩니다.


CollectionView 에 담겨진 데이터를 화면에 하나씩 나타내도록 하여

탐색하는 코드를 알아봅니다.

 

Person.cs

using System.ComponentModel;

 

namespace WpfApp

{

    public class Person : INotifyPropertyChanged

    {

        /// <summary>

        /// 속성변경 이벤트입니다.

        /// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        string name = "";

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        string nickName = "";

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        public string Name

        {

            set

            {

                this.name = value;

                OnPropertyChanged(nameof(Name));

            }

            get { return name; }

        }

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        public string NickName

        {

            set

            {

                nickName = value;

                OnPropertyChanged(nameof(NickName));

            }

            get { return nickName; }

        }

 

        /// <summary>

        /// 속성 값이 변경될 때 발생합니다.

        /// </summary>

        /// <param name="propertyName"></param>

        protected virtual void OnPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

}

 

 

MainWindow.xaml

<Window x:Class="WpfApp.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="400">

    <StackPanel>

        <TextBox

            Margin="12" Height="50" VerticalContentAlignment="Center"

            Text="{Binding Name,

                   Mode=TwoWay,

                   UpdateSourceTrigger=PropertyChanged}" />

        <TextBox

            Margin="12" Height="50" VerticalContentAlignment="Center"

            Text="{Binding NickName,

                   Mode=TwoWay,

                   UpdateSourceTrigger=PropertyChanged}" />

        

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">

            <Button Name="prevButton" Content="Prev" Padding="10" Margin="10" Click="prevButton_Click"/>

            <Button Name="nextButton" Content="Next" Padding="10" Margin="10" Click="nextButton_Click"/>

        </StackPanel>

    </StackPanel>

</Window>

 

 

MainWindow.xaml.cs

using System;

using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Linq;

using System.Windows;

using System.Windows.Data;

 

namespace WpfApp

{

    public partial class MainWindow : Window

    {

        /// <summary>

        /// 데이터 collectionView 입니다.

        /// </summary>

        ICollectionView collectionView;

 

        public MainWindow()

        {

            InitializeComponent();

 

            ObservableCollection<Person> datas = new ObservableCollection<Person>();

 

            datas.Add(new Person(){ Name = "Kang",  NickName = "Super" });

            datas.Add(new Person(){ Name = "An",    NickName = "Father" });

            datas.Add(new Person(){ Name = "Jang",  NickName = "Marvel" });

 

            this.collectionView = CollectionViewSource.GetDefaultView(datas);

            this.collectionView.CurrentChanged += CollectionView_CurrentChanged; ;

 

            this.collectionView.SortDescriptions.Add(new SortDescription(nameof(Person.Name), ListSortDirection.Ascending));

 

            this.DataContext = this.collectionView;

 

            // 처음값으로 이동시킵니다.

            this.collectionView.MoveCurrentToFirst();

        }

 

        /// <summary>

        /// 이전 값으로 이동하는 버튼 클릭이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void prevButton_Click(object sender, RoutedEventArgs e)

        {

            this.collectionView.MoveCurrentToPrevious();

        }

 

        /// <summary>

        /// 다음 값으로 이동하는 버튼 클릭이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void nextButton_Click(object sender, RoutedEventArgs e)

        {

            this.collectionView.MoveCurrentToNext();

        }

 

        /// <summary>

        /// CollectionView 현재값이 변경되었을때 발생되는 이벤트입니다.

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="args"></param>

        private void CollectionView_CurrentChanged(object sender, EventArgs e)

        {

            // 이전/다음 항목 존재여부에 따라 이전/다음 버튼을 활성화하거나 비활성화 합니다.

            this.prevButton.IsEnabled = this.collectionView.CurrentPosition > 0;

            this.nextButton.IsEnabled = this.collectionView.CurrentPosition < this.collectionView.Cast<object>().Count() - 1;

        }

    }

}

 

 


 

CollectionView 를 이용해 다양한 기능을 처리할수 있습니다.

여기선 데이터 정렬하는 기능을 알아봅니다.

 

먼저 데이터로 사용할 Class 를 정의합니다.

 

Person.cs

 

using System.ComponentModel;

 

namespace WpfApp

{

    public class Person : INotifyPropertyChanged

    {

        /// <summary>

        /// 속성변경 이벤트입니다.

        /// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        string name = "";

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        string nickName = "";

 

        /// <summary>

        /// 이름입니다.

        /// </summary>

        public string Name

        {

            set

            {

                this.name = value;

                OnPropertyChanged(nameof(Name));

            }

            get { return name; }

        }

 

        /// <summary>

        /// 별명입니다.

        /// </summary>

        public string NickName

        {

            set

            {

                nickName = value;

                OnPropertyChanged(nameof(NickName));

            }

            get { return nickName; }

        }

 

        /// <summary>

        /// 속성 값이 변경될 때 발생합니다.

        /// </summary>

        /// <param name="propertyName"></param>

        protected virtual void OnPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

}

 

 

MainWindow.xaml

<Window x:Class="WpfApp.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800">

    <StackPanel>

        <ListBox Name="listbox" Width="300" Height="300" Margin="24">

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <StackPanel Orientation="Horizontal">

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

                        <TextBlock Text="      " />

                        <TextBlock Text="{Binding NickName}" />

                    </StackPanel>

                </DataTemplate>

            </ListBox.ItemTemplate>

        </ListBox>

    </StackPanel>

</Window>

 

 

MainWindow.xaml.cs

 

using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Windows;

using System.Windows.Data;

 

namespace WpfApp

{

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

 

            ObservableCollection<Person> datas = new ObservableCollection<Person>();

 

            datas.Add(new Person(){ Name = "Kang",  NickName = "Super" });

            datas.Add(new Person(){ Name = "An",    NickName = "Father" });

            datas.Add(new Person(){ Name = "Jang",  NickName = "Marvel" });

 

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(datas);

 

            collectionView.SortDescriptions.Add(new SortDescription(nameof(Person.Name), ListSortDirection.Ascending));

 

            this.listbox.ItemsSource = collectionView;

        }

    }

}

 

 

위 코드에서 보듯이 CollectionView 의 SortDescriptions 를 사용하여 정렬기준을 줄수 있습니다.

 

 

 

// 2020 년 의 2월 일수를 가져옵니다. (결과:29)

int days = DateTime.DaysInMonth(2020, 2);

Control 에서 원하는 Control 을 선택하면

상단에 해당 Control 이 표시되고

Dump 의  Template Property 를 선택하면 하단에 ControlTemplate 객체를 XAML 포맷으로 보여준다.



AnalysisControlTemplate.exe


출처 : 찰스 펫졸드

ControlTemplate 은 컨트롤의 모습이나 이벤트 처리등을 미리 정의해 놓고 가져다 쓰는 것을 말합니다.

아래 예시를 보시면 아시겠지만 RadioButton 앞의 라디오 박스가 사라지고

선택시 글자를 굵게 표시하고 주변으로 사각형이 그려집니다.

 

<Window x:Class="WpfApp.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800">

    <StackPanel>

        <StackPanel.Resources>

            <ControlTemplate

                 x:Key="rectRadioButton"

                 TargetType="{x:Type RadioButton}">

                <Border

                    Name="border"

                    BorderBrush="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"

                    CornerRadius="0"

                    Padding="10"

                    BorderThickness="0"

                    Margin="2"

                    Width="250">

                    <ContentPresenter

                        Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center"/>

                </Border>

                <ControlTemplate.Triggers>

                    <Trigger

                         Property="IsChecked"

                         Value="True">

                        <Setter

                             TargetName="border"

                             Property="BorderThickness"

                             Value="3" />

                        <Setter

                             Property="FontWeight"

                             Value="Bold" />

                    </Trigger>

                </ControlTemplate.Triggers>

            </ControlTemplate>

        </StackPanel.Resources>

        <GroupBox

             HorizontalAlignment="Center"

             VerticalAlignment="Center"

             FontSize="12pt"

             Header="Select Option">

            <StackPanel>

                <RadioButton

                    Template="{StaticResource rectRadioButton}"

                    HorizontalAlignment="Center"

                    Content="Template RadioButton 1"

                    IsChecked="True" />

                <RadioButton

                     Template="{StaticResource rectRadioButton}"

                     HorizontalAlignment="Center"

                     Content="Template RadioButton 2" />

                <RadioButton

                     Template="{StaticResource rectRadioButton}"

                     HorizontalAlignment="Center"

                     Content="Template RadioButton 3" />

                <RadioButton

                     Template="{StaticResource rectRadioButton}"

                     HorizontalAlignment="Center"

                     Content="Template RadioButton 4" />

            </StackPanel>

        </GroupBox>

    </StackPanel>

</Window>

 

 

 

Style.Triggers 를 이용하여 Control 에 액션을 취한경우 어떠한 처리를 할 수 있습니다.

아래 예시는 Button, Label 에 마우스를 올렸을때 글자가 파란색으로 굵게 나타도록 한 것입니다.

Button 은 클릭시 글자 색을 변경합니다.

 

<Window x:Class="WpfApp3.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800">

    <StackPanel>

        <StackPanel.Resources>

            <Style

                x:Key="normal">

                <Setter

                    Property="Control.FontSize"

                    Value="20" />

                <Setter

                    Property="Control.HorizontalAlignment"

                    Value="Center" />

                <Style.Triggers>

                    <Trigger

                        Property="Control.IsMouseOver"

                        Value="true">

                        <Setter

                            Property="Control.FontWeight"

                            Value="Bold" />

                        <Setter

                            Property="Control.Foreground"

                            Value="Blue" />

                    </Trigger>

                    <Trigger

                        Property="Button.IsPressed"

                        Value="true">

                        <Setter

                            Property="Control.Foreground"

                            Value="Red" />

                    </Trigger>

                </Style.Triggers>

            </Style>

        </StackPanel.Resources>

        <Button Style="{StaticResource normal}" Content="Test Button"/>

        <Label Style="{StaticResource normal}" Content="Test Label"/>

    </StackPanel>

</Window>

 

 

 

* MouseOver

  >     >

 

* Button Click

 

WebView 에 특정 url 을 보여주려고 했는데 아래 처럼 에러가 발생되었습니다.

 

net::ERR_CLEARTEXT_NOT_PERMITTED

 

 

확인해 보니 Android OS 9 Pie 버전부터는 WebView에 "http://" URL 접근이 안된다고 합니다.

 

해당 오류를 해결하기위해선 안드로이드 프로젝트의 AndroidManifest.xml 파일의 내용에

아래 굵게 표시된 내용을 추가하면 됩니다. (android:usesCleartextTraffic="true")

 

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.test" android:installLocation="auto">

<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />

<application

           android:label="test.Android"

           android:usesCleartextTraffic="true">

       </application>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<uses-permission android:name="android.permission.INTERNET" />

</manifest>

 

위처리를 하고 다시 앱을 실행하니 아래처럼 url 내용이 잘 나타났습니다.