방법: DataGrid 컨트롤에서 데이터 그룹화, 정렬 및 필터링
데이터를 그룹화, 정렬 및 필터링하여 다양한 방법으로 DataGrid의 데이터를 보는 것이 유용한 경우가 많습니다. DataGrid에서 데이터를 그룹화, 정렬 및 필터링하려면 이러한 함수를 지원하는 CollectionView에 데이터를 바인딩합니다. 그런 다음, 기본 원본 데이터에 영향을 주지 않고 CollectionView에서 해당 데이터로 작업할 수 있습니다. 컬렉션 뷰의 변경 내용은 DataGrid UI(사용자 인터페이스)에 반영됩니다.
CollectionView 클래스는 IEnumerable 인터페이스를 구현하는 데이터 원본에 대한 그룹화 및 정렬 기능을 제공합니다. CollectionViewSource 클래스를 사용하면 XAML에서 CollectionView의 속성을 설정할 수 있습니다.
이 예제에서는 Task
개체의 컬렉션이 CollectionViewSource에 바인딩됩니다. CollectionViewSource는 DataGrid에 대한 ItemsSource로 사용됩니다. 그룹화, 정렬 및 필터링은 CollectionViewSource에서 수행되며 DataGrid UI에 표시됩니다.
DataGrid의 그룹화된 데이터
CollectionViewSource를 ItemsSource로 사용
DataGrid 컨트롤에서 데이터를 그룹화하고 정렬하며 필터링하려면 이러한 함수를 지원하는 CollectionView에 DataGrid를 바인딩합니다. 이 예제에서 DataGrid는 Task
개체의 List<T>에 대해 이러한 함수를 제공하는 CollectionViewSource에 바인딩됩니다.
DataGrid를 CollectionViewSource에 바인딩하려면
IEnumerable 인터페이스를 구현하는 데이터 컬렉션을 만듭니다.
List<T>를 컬렉션을 만드는 데 사용하는 경우, List<T>의 인스턴스를 인스턴스화하는 대신 List<T>에서 상속되는 새 클래스를 만들어야 합니다. 이렇게 하면 XAML에서 컬렉션에 데이터를 바인딩할 수 있습니다.
참고
DataGrid가 속성 변경 및 편집에 올바르게 응답하려면 컬렉션의 개체가 INotifyPropertyChanged 변경된 인터페이스와 IEditableObject 인터페이스를 구현해야 합니다. 자세한 내용은 속성 변경 알림 구현을 참조하세요.
// Requires using System.Collections.ObjectModel; public class Tasks : ObservableCollection<Task> { // Creating the Tasks collection in this way enables data binding from XAML. }
' Requires Imports System.Collections.ObjectModel Public Class Tasks Inherits ObservableCollection(Of Task) ' Creating the Tasks collection in this way enables data binding from XAML. End Class
XAML에서 컬렉션 클래스의 인스턴스를 만들고 x:Key 지시문을 설정합니다.
XAML에서 CollectionViewSource 클래스의 인스턴스를 만들고 x:Key 지시문을 설정하며 컬렉션 클래스의 인스턴스를 Source로 설정합니다.
<Window.Resources> <local:Tasks x:Key="tasks" /> <CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}" Filter="CollectionViewSource_Filter"> </CollectionViewSource> </Window.Resources>
DataGrid 클래스의 인스턴스를 만들고 ItemsSource 속성을 CollectionViewSource로 설정합니다.
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding Source={StaticResource cvsTasks}}" CanUserAddRows="False">
코드에서 CollectionViewSource에 액세스하려면 GetDefaultView 메서드를 사용하여 CollectionViewSource에 대한 참조를 가져옵니다.
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource)
DataGrid에서 항목 그룹화
DataGrid에서 항목의 그룹화 방법을 지정하려면 PropertyGroupDescription 형식을 사용하여 원본 뷰의 항목을 그룹화합니다.
XAML을 사용하여 DataGrid의 항목을 그룹화하려면
그룹화할 속성을 지정하는 PropertyGroupDescription을 만듭니다. XAML 또는 코드에서 속성을 지정할 수 있습니다.
XAML에서 PropertyName을 그룹화할 속성의 이름으로 설정합니다.
코드에서 그룹화할 속성의 이름을 생성자에 전달합니다.
CollectionViewSource.GroupDescriptions 컬렉션에 PropertyGroupDescription을 추가합니다.
GroupDescriptions 컬렉션에 PropertyGroupDescription의 추가 인스턴스를 추가하여 더 많은 그룹화 수준을 추가합니다.
<CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="ProjectName"/> <PropertyGroupDescription PropertyName="Complete"/> </CollectionViewSource.GroupDescriptions>
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource); if (cvTasks != null && cvTasks.CanGroup == true) { cvTasks.GroupDescriptions.Clear(); cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName")); cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("Complete")); }
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource) If cvTasks IsNot Nothing And cvTasks.CanGroup = True Then cvTasks.GroupDescriptions.Clear() cvTasks.GroupDescriptions.Add(New PropertyGroupDescription("ProjectName")) cvTasks.GroupDescriptions.Add(New PropertyGroupDescription("Complete")) End If
그룹을 제거하려면 GroupDescriptions 컬렉션에서 PropertyGroupDescription을 제거합니다.
모든 그룹을 제거하려면 GroupDescriptions 컬렉션에서 Clear 메서드를 호출합니다.
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource); if (cvTasks != null) { cvTasks.GroupDescriptions.Clear(); }
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource) If cvTasks IsNot Nothing Then cvTasks.GroupDescriptions.Clear() End If
DataGrid에서 항목이 그룹화되면 각 그룹의 모양을 지정하는 GroupStyle을 정의할 수 있습니다. GroupStyle은 DataGrid의 GroupStyle 컬렉션에 추가하여 적용합니다. 여러 수준의 그룹화가 있는 경우, 각 그룹 수준에 다른 스타일을 적용할 수 있습니다. 스타일은 정의된 순서대로 적용됩니다. 예를 들어, 두 스타일을 정의하는 경우 첫 번째 스타일이 최상위 행 그룹에 적용됩니다. 두 번째 스타일은 두 번째 수준 이하의 모든 행 그룹에 적용됩니다. GroupStyle의 DataContext는 그룹이 나타내는 CollectionViewGroup입니다.
행 그룹 헤더의 모양을 변경하려면
행 그룹의 모양을 정의하는 GroupStyle을 만듭니다.
GroupStyle을
<DataGrid.GroupStyle>
태그 내부에 넣습니다.<DataGrid.GroupStyle> <!-- Style for groups at top level. --> <GroupStyle> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Margin" Value="0,0,0,5"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupItem}"> <Expander IsExpanded="True" Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE" BorderThickness="1,1,1,5"> <Expander.Header> <DockPanel> <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/> <TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/> </DockPanel> </Expander.Header> <Expander.Content> <ItemsPresenter /> </Expander.Content> </Expander> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> </GroupStyle> <!-- Style for groups under the top level. --> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <DockPanel Background="LightBlue"> <TextBlock Text="{Binding Path=Name, Converter={StaticResource completeConverter}}" Foreground="Blue" Margin="30,0,0,0" Width="100"/> <TextBlock Text="{Binding Path=ItemCount}" Foreground="Blue"/> </DockPanel> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </DataGrid.GroupStyle>
DataGrid에서 항목 정렬
DataGrid에서 항목의 정렬 방법을 지정하려면 SortDescription 형식을 사용하여 원본 뷰의 항목을 정렬합니다.
DataGrid에서 항목을 정렬하려면
정렬할 속성을 지정하는 SortDescription을 만듭니다. XAML 또는 코드에서 속성을 지정할 수 있습니다.
XAML에서 PropertyName을 정렬할 속성의 이름으로 설정합니다.
코드에서 정렬할 속성의 이름과 ListSortDirection을 생성자에 전달합니다.
CollectionViewSource.SortDescriptions 컬렉션에 SortDescription을 추가합니다.
SortDescription의 추가 인스턴스를 추가 속성에 따라 정렬할 SortDescriptions 컬렉션에 추가합니다.
<CollectionViewSource.SortDescriptions> <!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. --> <scm:SortDescription PropertyName="ProjectName"/> <scm:SortDescription PropertyName="Complete" /> <scm:SortDescription PropertyName="DueDate" /> </CollectionViewSource.SortDescriptions>
// Requires using System.ComponentModel; ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource); if (cvTasks != null && cvTasks.CanSort == true) { cvTasks.SortDescriptions.Clear(); cvTasks.SortDescriptions.Add(new SortDescription("ProjectName", ListSortDirection.Ascending)); cvTasks.SortDescriptions.Add(new SortDescription("Complete", ListSortDirection.Ascending)); cvTasks.SortDescriptions.Add(new SortDescription("DueDate", ListSortDirection.Ascending)); }
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource) If cvTasks IsNot Nothing And cvTasks.CanSort = True Then cvTasks.SortDescriptions.Clear() cvTasks.SortDescriptions.Add(New SortDescription("ProjectName", ListSortDirection.Ascending)) cvTasks.SortDescriptions.Add(New SortDescription("Complete", ListSortDirection.Ascending)) cvTasks.SortDescriptions.Add(New SortDescription("DueDate", ListSortDirection.Ascending)) End If
DataGrid에서 항목 필터링
CollectionViewSource를 사용하여 DataGrid에서 항목을 필터링하려면 CollectionViewSource.Filter 이벤트에 대한 처리기에 필터링 논리를 제공합니다.
DataGrid에서 항목을 필터링하려면
CollectionViewSource.Filter 이벤트에 대한 처리기를 추가합니다.
Filter 이벤트 처리기에서 필터링 논리를 정의합니다.
보기를 새로 고칠 때마다 필터가 적용됩니다.
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}" Filter="CollectionViewSource_Filter">
private void CollectionViewSource_Filter(object sender, FilterEventArgs e) { Task t = e.Item as Task; if (t != null) // If filter is turned on, filter completed items. { if (this.cbCompleteFilter.IsChecked == true && t.Complete == true) e.Accepted = false; else e.Accepted = true; } }
Private Sub CollectionViewSource_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs) Dim t As Task = e.Item If t IsNot Nothing Then ' If filter is turned on, filter completed items. If Me.cbCompleteFilter.IsChecked = True And t.Complete = True Then e.Accepted = False Else e.Accepted = True End If End If End Sub
또는 필터링 논리를 제공하는 메서드를 만들고 필터를 적용하도록 CollectionView.Filter 속성을 설정하여 DataGrid에서 항목을 필터링할 수 있습니다. 이 메서드의 예제를 보려면 뷰에서 데이터 필터링을 참조하세요.
예제
다음 예제에서는 CollectionViewSource에서 Task
데이터를 그룹화, 정렬 및 필터링하고 이렇게 그룹화, 정렬 및 필터링된 Task
데이터를 DataGrid에 표시하는 방법을 보여줍니다. CollectionViewSource는 DataGrid에 대한 ItemsSource로 사용됩니다. 그룹화, 정렬 및 필터링은 CollectionViewSource에서 수행되며 DataGrid UI에 표시됩니다.
이 예제를 테스트하려면 프로젝트 이름과 일치하도록 DGGroupSortFilterExample 이름을 조정해야 합니다. Visual Basic을 사용하는 경우, Window에 대한 클래스 이름을 다음으로 변경해야 합니다.
<Window x:Class="MainWindow"
<Window x:Class="DGGroupSortFilterExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DGGroupSortFilterExample"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="Group, Sort, and Filter Example" Height="575" Width="525">
<Window.Resources>
<local:CompleteConverter x:Key="completeConverter" />
<local:Tasks x:Key="tasks" />
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}"
Filter="CollectionViewSource_Filter">
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="ProjectName"/>
<scm:SortDescription PropertyName="Complete" />
<scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ProjectName"/>
<PropertyGroupDescription PropertyName="Complete"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<DataGrid x:Name="dataGrid1"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False">
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE" BorderThickness="1,1,1,5">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
<!-- Style for groups under the top level. -->
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<DockPanel Background="LightBlue">
<TextBlock Text="{Binding Path=Name, Converter={StaticResource completeConverter}}" Foreground="Blue" Margin="30,0,0,0" Width="100"/>
<TextBlock Text="{Binding Path=ItemCount}" Foreground="Blue"/>
</DockPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="White" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBlock Text=" Filter completed items " VerticalAlignment="Center" />
<CheckBox x:Name="cbCompleteFilter" VerticalAlignment="Center"
Checked="CompleteFilter_Changed" Unchecked="CompleteFilter_Changed" />
<Button Content="Remove Groups" Margin="10,2,2,2" Click="UngroupButton_Click" />
<Button Content="Group by Project/Status" Margin="2" Click="GroupButton_Click" />
</StackPanel>
</Grid>
</Window>
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace DGGroupSortFilterExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Get a reference to the tasks collection.
Tasks _tasks = (Tasks)this.Resources["tasks"];
// Generate some task data and add it to the task list.
for (int i = 1; i <= 14; i++)
{
_tasks.Add(new Task()
{
ProjectName = "Project " + ((i % 3) + 1).ToString(),
TaskName = "Task " + i.ToString(),
DueDate = DateTime.Now.AddDays(i),
Complete = (i % 2 == 0)
});
}
}
private void UngroupButton_Click(object sender, RoutedEventArgs e)
{
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null)
{
cvTasks.GroupDescriptions.Clear();
}
}
private void GroupButton_Click(object sender, RoutedEventArgs e)
{
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null && cvTasks.CanGroup == true)
{
cvTasks.GroupDescriptions.Clear();
cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName"));
cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("Complete"));
}
}
private void CompleteFilter_Changed(object sender, RoutedEventArgs e)
{
// Refresh the view to apply filters.
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource).Refresh();
}
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
Task t = e.Item as Task;
if (t != null)
// If filter is turned on, filter completed items.
{
if (this.cbCompleteFilter.IsChecked == true && t.Complete == true)
e.Accepted = false;
else
e.Accepted = true;
}
}
}
[ValueConversion(typeof(Boolean), typeof(String))]
public class CompleteConverter : IValueConverter
{
// This converter changes the value of a Tasks Complete status from true/false to a string value of
// "Complete"/"Active" for use in the row group header.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool complete = (bool)value;
if (complete)
return "Complete";
else
return "Active";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string strComplete = (string)value;
if (strComplete == "Complete")
return true;
else
return false;
}
}
// Task Class
// Requires using System.ComponentModel;
public class Task : INotifyPropertyChanged, IEditableObject
{
// The Task class implements INotifyPropertyChanged and IEditableObject
// so that the datagrid can properly respond to changes to the
// data collection and edits made in the DataGrid.
// Private task data.
private string m_ProjectName = string.Empty;
private string m_TaskName = string.Empty;
private DateTime m_DueDate = DateTime.Now;
private bool m_Complete = false;
// Data for undoing canceled edits.
private Task temp_Task = null;
private bool m_Editing = false;
// Public properties.
public string ProjectName
{
get { return this.m_ProjectName; }
set
{
if (value != this.m_ProjectName)
{
this.m_ProjectName = value;
NotifyPropertyChanged("ProjectName");
}
}
}
public string TaskName
{
get { return this.m_TaskName; }
set
{
if (value != this.m_TaskName)
{
this.m_TaskName = value;
NotifyPropertyChanged("TaskName");
}
}
}
public DateTime DueDate
{
get { return this.m_DueDate; }
set
{
if (value != this.m_DueDate)
{
this.m_DueDate = value;
NotifyPropertyChanged("DueDate");
}
}
}
public bool Complete
{
get { return this.m_Complete; }
set
{
if (value != this.m_Complete)
{
this.m_Complete = value;
NotifyPropertyChanged("Complete");
}
}
}
// Implement INotifyPropertyChanged interface.
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// Implement IEditableObject interface.
public void BeginEdit()
{
if (m_Editing == false)
{
temp_Task = this.MemberwiseClone() as Task;
m_Editing = true;
}
}
public void CancelEdit()
{
if (m_Editing == true)
{
this.ProjectName = temp_Task.ProjectName;
this.TaskName = temp_Task.TaskName;
this.DueDate = temp_Task.DueDate;
this.Complete = temp_Task.Complete;
m_Editing = false;
}
}
public void EndEdit()
{
if (m_Editing == true)
{
temp_Task = null;
m_Editing = false;
}
}
}
// Requires using System.Collections.ObjectModel;
public class Tasks : ObservableCollection<Task>
{
// Creating the Tasks collection in this way enables data binding from XAML.
}
}
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Class MainWindow
Public Sub New()
InitializeComponent()
' Get a reference to the tasks collection.
Dim _tasks As Tasks = Me.Resources("tasks")
' Generate some task data and add it to the task list.
For index = 1 To 14
_tasks.Add(New Task() With _
{.ProjectName = "Project " & ((index Mod 3) + 1).ToString(), _
.TaskName = "Task " & index.ToString(), _
.DueDate = Date.Now.AddDays(index), _
.Complete = (index Mod 2 = 0) _
})
Next
End Sub
Private Sub UngroupButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource)
If cvTasks IsNot Nothing Then
cvTasks.GroupDescriptions.Clear()
End If
End Sub
Private Sub GroupButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource)
If cvTasks IsNot Nothing And cvTasks.CanGroup = True Then
cvTasks.GroupDescriptions.Clear()
cvTasks.GroupDescriptions.Add(New PropertyGroupDescription("ProjectName"))
cvTasks.GroupDescriptions.Add(New PropertyGroupDescription("Complete"))
End If
End Sub
Private Sub CompleteFilter_Changed(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
' Refresh the view to apply filters.
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource).Refresh()
End Sub
Private Sub CollectionViewSource_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
Dim t As Task = e.Item
If t IsNot Nothing Then
' If filter is turned on, filter completed items.
If Me.cbCompleteFilter.IsChecked = True And t.Complete = True Then
e.Accepted = False
Else
e.Accepted = True
End If
End If
End Sub
End Class
Public Class CompleteConverter
Implements IValueConverter
' This converter changes the value of a Tasks Complete status from true/false to a string value of
' "Complete"/"Active" for use in the row group header.
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
Dim complete As Boolean = value
If complete = True Then
Return "Complete"
Else
Return "Active"
End If
End Function
Public Function ConvertBack1(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Dim strComplete As String = value
If strComplete = "Complete" Then
Return True
Else
Return False
End If
End Function
End Class
' Task class
' Requires Imports System.ComponentModel
Public Class Task
Implements INotifyPropertyChanged, IEditableObject
' The Task class implements INotifyPropertyChanged and IEditableObject
' so that the datagrid can properly respond to changes to the
' data collection and edits made in the DataGrid.
' Private task data.
Private m_ProjectName As String = String.Empty
Private m_TaskName As String = String.Empty
Private m_DueDate As DateTime = Date.Now
Private m_Complete As Boolean = False
' Data for undoing canceled edits.
Private temp_Task As Task = Nothing
Private m_Editing As Boolean = False
' Public properties.
Public Property ProjectName() As String
Get
Return Me.m_ProjectName
End Get
Set(ByVal value As String)
If Not value = Me.m_ProjectName Then
Me.m_ProjectName = value
NotifyPropertyChanged("ProjectName")
End If
End Set
End Property
Public Property TaskName() As String
Get
Return Me.m_TaskName
End Get
Set(ByVal value As String)
If Not value = Me.m_TaskName Then
Me.m_TaskName = value
NotifyPropertyChanged("TaskName")
End If
End Set
End Property
Public Property DueDate() As Date
Get
Return Me.m_DueDate
End Get
Set(ByVal value As Date)
If Not value = Me.m_DueDate Then
Me.m_DueDate = value
NotifyPropertyChanged("DueDate")
End If
End Set
End Property
Public Property Complete() As Boolean
Get
Return Me.m_Complete
End Get
Set(ByVal value As Boolean)
If Not value = Me.m_Complete Then
Me.m_Complete = value
NotifyPropertyChanged("Complete")
End If
End Set
End Property
' Implement INotifyPropertyChanged interface.
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
' Implement IEditableObject interface.
Public Sub BeginEdit() Implements IEditableObject.BeginEdit
If Not Me.m_Editing Then
Me.temp_Task = Me.MemberwiseClone()
Me.m_Editing = True
End If
End Sub
Public Sub CancelEdit() Implements IEditableObject.CancelEdit
If m_Editing = True Then
Me.ProjectName = Me.temp_Task.ProjectName
Me.TaskName = Me.temp_Task.TaskName
Me.DueDate = Me.temp_Task.DueDate
Me.Complete = Me.temp_Task.Complete
Me.m_Editing = False
End If
End Sub
Public Sub EndEdit() Implements IEditableObject.EndEdit
If m_Editing = True Then
Me.temp_Task = Nothing
Me.m_Editing = False
End If
End Sub
End Class
' Requires Imports System.Collections.ObjectModel
Public Class Tasks
Inherits ObservableCollection(Of Task)
' Creating the Tasks collection in this way enables data binding from XAML.
End Class
참고 항목
.NET Desktop feedback
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기