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

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"

  1. 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.

    HinweisHinweis

    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.
    }
    
  2. Erstellen Sie in XAML eine Instanz der Auflistungsklasse, und legen Sie die x:Key-Direktive fest.

  3. 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>
    
  4. 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">
    
  5. 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

  1. Erstellen Sie eine PropertyGroupDescription, die die Eigenschaft angibt, nach der gruppiert werden soll. Sie können die Eigenschaft in XAML oder im Code festlegen.

    1. Legen Sie in XAML den PropertyName auf den Namen der Eigenschaft fest, nach der gruppiert werden soll.

    2. Übergeben Sie im Code den Namen der Eigenschaft, auf der die Gruppierung basieren soll, an den Konstruktor.

  2. Fügen Sie die PropertyGroupDescription der CollectionViewSource.GroupDescriptions-Auflistung hinzu.

  3. 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"));
    }
    
  4. Um eine Gruppe zu entfernen, entfernen Sie die PropertyGroupDescription aus der GroupDescriptions-Auflistung.

  5. 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

  1. Erstellen Sie einen GroupStyle, der die Darstellung der Zeilengruppe definiert.

  2. 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

  1. Erstellen Sie eine SortDescription, die die Eigenschaft angibt, nach der sortiert werden soll. Sie können die Eigenschaft in XAML oder im Code festlegen.

    1. Legen Sie in XAML den PropertyName auf den Namen der Eigenschaft fest, nach der sortiert werden soll.

    2. Übergeben Sie im Code den Namen der Eigenschaft, auf dem die Sortierung basieren soll, und die ListSortDirection an den Konstruktor.

  2. Fügen Sie die SortDescription der CollectionViewSource.SortDescriptions-Auflistung hinzu.

  3. 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

  1. Fügen Sie einen Handler für das CollectionViewSource.Filter-Ereignis hinzu.

  2. 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

Konzepte

Übersicht über Datenbindung