Gewusst wie: Gruppieren, Sortieren und Filtern von Daten mit dem DataGrid-Steuerelement
Es ist oft hilfreich, Daten in einem DataGrid durch Gruppieren, Sortieren und Filtern der Daten auf verschiedene Weise anzuzeigen. Zum Gruppieren, Sortieren und Filtern der Daten in einem DataGrid, binden Sie es an eine CollectionView, die diese Funktionen unterstützt. Anschließend können Sie mit den Daten in der CollectionView arbeiten, ohne die zugrunde liegenden Quelldaten zu beeinflussen. Die Änderungen in der Auflistungsansicht werden in der DataGrid-Benutzeroberfläche wiedergegeben.
Die CollectionView-Klasse stellt Gruppierungs- und Sortierungsfunktionen für eine Datenquelle bereit, die die IEnumerable-Schnittstelle implementiert. Die CollectionViewSource-Klasse ermöglicht es Ihnen, die Eigenschaften einer CollectionView in XAML festzulegen.
In diesem Beispiel ist eine Auflistung von Task-Objekten an eine CollectionViewSource gebunden. Die CollectionViewSource wird als ItemsSource für das DataGrid verwendet. Gruppierung, Sortierung und Filterung werden für die CollectionViewSource ausgeführt und in der DataGrid-Benutzeroberfläche angezeigt.
Gruppierte Daten in einem DataGrid
Verwenden von "CollectionViewSource" als "ItemsSource"
Zum Gruppieren, Sortieren und Filtern der Daten in einem DataGrid-Steuerelement binden Sie das DataGrid an eine CollectionView, die diese Funktionen unterstützt. In diesem Beispiel wird das DataGrid an eine CollectionViewSource gebunden, die diese Funktionen für eine List<T> mit Task-Objekten bereitstellt.
So binden Sie ein DataGrid an eine "CollectionViewSource"
Erstellen Sie eine Datensammlung, die die IEnumerable-Schnittstelle implementiert.
Wenn Sie List<T> verwenden, um die Auflistung zu erstellen, sollten Sie eine neue Klasse erstellen, die von List<T> erbt, anstatt eine Instanz von List<T> zu instanziieren. Auf diese Weise können Sie in XAML eine Datenbindung an die Auflistung vornehmen.
Hinweis Die Objekte in der Auflistung müssen die geänderte INotifyPropertyChanged-Schnittstelle und die IEditableObject-Schnittstelle implementieren, damit das DataGrid ordnungsgemäß auf Eigenschaftenänderungen und Bearbeitungen reagiert.Weitere Informationen finden Sie unter Gewusst wie: Implementieren von Benachrichtigungen bei Eigenschaftenänderungen.
' 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
// Requires using System.Collections.ObjectModel; public class Tasks : ObservableCollection<Task> { // Creating the Tasks collection in this way enables data binding from XAML. }
Erstellen Sie in XAML eine Instanz der Auflistungsklasse, und legen Sie die x:Key-Direktive fest.
Erstellen Sie in XAML eine Instanz der CollectionViewSource-Klasse, legen Sie die x:Key-Direktive fest, und legen Sie die Instanz der Auflistungsklasse als Source fest.
<Window.Resources> <local:Tasks x:Key="tasks" /> <CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}" Filter="CollectionViewSource_Filter"> </CollectionViewSource> </Window.Resources>
Erstellen Sie eine Instanz der DataGrid-Klasse, und legen Sie die ItemsSource-Eigenschaft auf die CollectionViewSource fest.
<DataGrid x:Name="dataGrid1" ItemsSource="{Binding Source={StaticResource cvsTasks}}" CanUserAddRows="False">
Um im Code auf die CollectionViewSource zuzugreifen, rufen Sie mit der GetDefaultView-Methode einen Verweis auf die CollectionViewSource ab.
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource)
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
Gruppieren von Elementen in einem DataGrid
Um anzugeben, wie Elemente in einem DataGrid gruppiert werden, gruppieren Sie die Elemente in der Quellansicht mithilfe des PropertyGroupDescription-Typs.
So gruppieren Sie Elemente in ein DataGrid mit XAML
Erstellen Sie eine PropertyGroupDescription, die die Eigenschaft angibt, nach der gruppiert werden soll. Sie können die Eigenschaft in XAML oder im Code festlegen.
Legen Sie in XAML den PropertyName auf den Namen der Eigenschaft fest, nach der gruppiert werden soll.
Übergeben Sie im Code den Namen der Eigenschaft, auf der die Gruppierung basieren soll, an den Konstruktor.
Fügen Sie die PropertyGroupDescription der CollectionViewSource.GroupDescriptions-Auflistung hinzu.
Fügen Sie der GroupDescriptions-Auflistung zusätzliche PropertyGroupDescription-Instanzen hinzu, um mehr Gruppierungsebenen hinzuzufügen.
<CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="ProjectName"/> <PropertyGroupDescription PropertyName="Complete"/> </CollectionViewSource.GroupDescriptions>
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
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")); }
Um eine Gruppe zu entfernen, entfernen Sie die PropertyGroupDescription aus der GroupDescriptions-Auflistung.
Um alle Gruppen zu entfernen, rufen Sie die Clear-Methode der GroupDescriptions-Auflistung auf.
Dim cvTasks As ICollectionView = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource) If cvTasks IsNot Nothing Then cvTasks.GroupDescriptions.Clear() End If
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource); if (cvTasks != null) { cvTasks.GroupDescriptions.Clear(); }
Wenn Elemente im DataGrid gruppiert werden, können Sie einen GroupStyle definieren, der die Darstellung jeder Gruppe angibt. Der GroupStyle wird angewendet, indem Sie ihn der GroupStyle-Auflistung des DataGrid hinzufügen. Wenn Sie über mehrere Gruppierungsebenen verfügen, können Sie auf die einzelnen Gruppenebenen unterschiedliche Stile anwenden. Die Stile werden in der Reihenfolge angewendet, in der sie definiert sind. Wenn Sie z. B. zwei Stile definieren, wird der erste Stil auf die Zeilengruppen der obersten Ebene angewendet. Der zweite Stil wird auf alle Zeilengruppen der zweiten Ebene und niedriger angewendet. Der DataContext des GroupStyle ist die CollectionViewGroup, die die Gruppe darstellt.
So ändern Sie die Darstellung von Zeilengruppenheadern
Erstellen Sie einen GroupStyle, der die Darstellung der Zeilengruppe definiert.
Platzieren Sie den GroupStyle innerhalb der <DataGrid.GroupStyle>-Tags.
<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>
Sortieren von Elementen in einem DataGrid
Um anzugeben, wie Elemente in einem DataGrid sortiert werden, sortieren Sie die Elemente in der Quellansicht mithilfe des SortDescription-Typs.
So sortieren Sie Elemente in einem DataGrid
Erstellen Sie eine SortDescription, die die Eigenschaft angibt, nach der sortiert werden soll. Sie können die Eigenschaft in XAML oder im Code festlegen.
Legen Sie in XAML den PropertyName auf den Namen der Eigenschaft fest, nach der sortiert werden soll.
Übergeben Sie im Code den Namen der Eigenschaft, auf dem die Sortierung basieren soll, und die ListSortDirection an den Konstruktor.
Fügen Sie die SortDescription der CollectionViewSource.SortDescriptions-Auflistung hinzu.
Fügen Sie der SortDescriptions-Auflistung zusätzliche Instanzen von SortDescription hinzu, um nach zusätzlichen Eigenschaften zu sortieren.
<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>
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
// 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)); }
Filtern von Elementen in einem DataGrid
Um Elemente in einem DataGrid mithilfe einer CollectionViewSource zu filtern, geben Sie die Filterlogik im Handler für das CollectionViewSource.Filter-Ereignis an.
So filtern Sie Elemente in einem DataGrid
Fügen Sie einen Handler für das CollectionViewSource.Filter-Ereignis hinzu.
Definieren Sie im Filter-Handler die Filterlogik.
Der Filter wird jedes Mal angewendet, wenn die Ansicht aktualisiert wird.
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}" Filter="CollectionViewSource_Filter">
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
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; } }
Alternativ können Sie Elemente in einem DataGrid filtern, indem Sie eine Methode erstellen, die die Filterlogik bereitstellt, und die CollectionView.Filter-Eigenschaft zum Anwenden des Filters festlegen. Ein Beispiel für diese Methode finden Sie unter Gewusst wie: Filtern von Daten in einer Ansicht.
Beispiel
Im folgenden Beispiel werden das Gruppieren, Sortieren und Filtern von Task-Daten in einer CollectionViewSource und das Anzeigen der gruppierten, sortierten und gefilterten Task-Daten in einem DataGrid veranschaulicht. Die CollectionViewSource wird als ItemsSource für das DataGrid verwendet. Gruppierung, Sortierung und Filterung werden für die CollectionViewSource ausgeführt und in der DataGrid-Benutzeroberfläche angezeigt.
Um dieses Beispiel zu testen, müssen Sie den Namen "DGGroupSortFilterExample" entsprechend dem Projektnamen anpassen. Wenn Sie Visual Basic verwenden, müssen Sie den Klassennamen für Window wie folgt ändern.
<Window x:Class="MainWindow"
<Window x:Class="DGGroupSortFilterExample.MainWindow"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
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
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.
}
}
Siehe auch
Aufgaben
Gewusst wie: Erstellen und Binden an ObservableCollection
Gewusst wie: Filtern von Daten in einer Ansicht
Gewusst wie: Sortieren von Daten in einer Ansicht
Gewusst wie: Sortieren und Gruppieren von Daten mit einer Ansicht in XAML