{"id":55000279,"date":"2021-08-01T00:00:00","date_gmt":"2021-12-31T14:21:05","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=279"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Daten_in_Listen_filtern_mit_ListCollectionView","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Daten_in_Listen_filtern_mit_ListCollectionView\/","title":{"rendered":"Daten in Listen filtern mit ListCollectionView"},"content":{"rendered":"<p><b>Daten aus einer SQL Server-Datenbank oder anderen Datenquellen k&ouml;nnen wir &uuml;ber das Entity Frame-work als Objekte zug&auml;nglich machen und auch als solche in Listen-Steuerelementen anzeigen. Aber wie sieht es mit weiteren Funktionen aus &#8211; etwa zum Filtern, Sortieren oder Gruppieren Dazu ben&ouml;tigen wir einige spezielle Techniken, von denen wir die zum Filtern von Daten nach bestimmten Kriterien im vorliegenden Artikel vorstellen. Dabei nutzen wir Filter f&uuml;r Felder mit verschiedenen Datentypen und in verschiedenen Kombinationen.<\/b><\/p>\n<h2>Beispieldaten<\/h2>\n<p>Als Beispielmaterial wollen wir diesmal nicht auf ein extra anzulegendes Entity Data Model zugreifen, sondern einfach eine Liste von <b>Kunde<\/b>-Elementen erstellen, die ihre Daten aus einer Funktion bezieht statt aus einer Datenbank. Damit wir ein wenig Spielmaterial haben, soll die <b>Kunde<\/b>-Klasse String-, Zahlen-, Datums- und Boolean-Werte enthalten. Die Klasse <b>Kunde <\/b>sieht daher wie folgt aus:<\/p>\n<pre>Partial Public Class Kunde\r\n     <span style=\"color:blue;\">Public <\/span>Property ID<span style=\"color:blue;\"> As <\/span>System.Int32\r\n     <span style=\"color:blue;\">Public <\/span>Property Firma<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Vorname<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Nachname<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Anrede<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Strasse<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property PLZ<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Ort<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Land<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property EMail<span style=\"color:blue;\"> As <\/span>System.String\r\n     <span style=\"color:blue;\">Public <\/span>Property Geburtsdatum<span style=\"color:blue;\"> As <\/span>System.DateTime\r\n     <span style=\"color:blue;\">Public <\/span>Property Alter<span style=\"color:blue;\"> As <\/span>System.Int32\r\n     <span style=\"color:blue;\">Public <\/span>Property Newsletter<span style=\"color:blue;\"> As <\/span>System.Boolean\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Um ein <b>ListView<\/b>-Steuerelement zu f&uuml;llen, ben&ouml;tigen wir Beispieldaten, die wir mit einer Funktion namens <b>GetKunden <\/b>bereitstellen. Diese f&uuml;gen wir im Code behind-Modul des Fensters <b>MainWindow <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>GetKunden()<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Kunde)\r\n     <span style=\"color:blue;\">Dim <\/span>Kunden<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> ObservableCollection(Of Kunde)\r\n     Kunden.Add(<span style=\"color:blue;\">New<\/span> Kunde() <span style=\"color:blue;\">With<\/span> {.ID = 1, .Firma = \"Krahn GbR\", .Vorname = \"Adi\", _\r\n        .Nachname = \"Stratmann\", .Anrede = \"Herr\", .Strasse = \"Kremser Stra&szlig;e 54\", .PLZ = \"10589\", _\r\n        .Ort = \"Berlin\", .Land = \"Deutschland\", .EMail = \"adi@stratmann.de\", _\r\n        .Geburtsdatum = \"20.02.1939\", .Alter = 82, .Newsletter = -1})\r\n     Kunden.Add(<span style=\"color:blue;\">New<\/span> Kunde() <span style=\"color:blue;\">With<\/span> {.ID = 2, .Firma = \"G&ouml;llner AG\", .Vorname = \"Heidi\", _\r\n         .Nachname = \"Eich\", .Anrede = \"Frau\", .Strasse = \"Moosstra&szlig;e 30\", .PLZ = \"42289\", _\r\n         .Ort = \"Wuppertal\", .Land = \"Deutschland\", .EMail = \"heidi@eich.de\", _\r\n         .Geburtsdatum = \"30.11.1971\", .Alter = 50, .Newsletter = 0})\r\n     Kunden.Add(<span style=\"color:blue;\">New<\/span> Kunde() <span style=\"color:blue;\">With<\/span> {.ID = 3, .Firma = \"Peukert GmbH & Co. KG\", .Vorname = \"Wernfried\", _\r\n         .Nachname = \"Birk\", .Anrede = \"Herr\", .Strasse = \"Wiener Stra&szlig;e 78\", .PLZ = \"22297\", _\r\n         .Ort = \"Hamburg\", .Land = \"Deutschland\", .EMail = \"wernfried@birk.de\", _\r\n         .Geburtsdatum = \"23.01.1931\", .Alter = 90, .Newsletter = -1})\r\n     ...\r\n     Kunden.Add(<span style=\"color:blue;\">New<\/span> Kunde() <span style=\"color:blue;\">With<\/span> {.ID = 100, .Firma = \"Krahn KG\", .Vorname = \"Rosemaria\", _\r\n         .Nachname = \"Grill\", .Anrede = \"Frau\", .Strasse = \"Kalvarienbergstra&szlig;e 35\", .PLZ = \"09131\", _\r\n         .Ort = \"Chemnitz\", .Land = \"Deutschland\", .EMail = \"rosemaria@grill.de\", _\r\n         .Geburtsdatum = \"02.10.2009\", .Alter = 12, .Newsletter = -1})\r\n     Return Kunden\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>In der Klasse <b>MainWindow <\/b>hinterlegen wir au&szlig;erdem noch eine private Variable f&uuml;r die Auflistung der Kunden:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>_Kunden<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Kunde)<\/pre>\n<p>Diese machen wir &uuml;ber die folgende &ouml;ffentlich deklarierte Property verf&uuml;gbar:<\/p>\n<pre><span style=\"color:blue;\">Public Property <\/span>Kunden<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Kunde)\r\n     Get\r\n         Return _Kunden\r\n     End Get\r\n     Set(value<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Kunde))\r\n         _Kunden = value\r\n     End <span style=\"color:blue;\">Set<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Schlie&szlig;lich sorgen wir in der Konstruktor-Methode der Klasse, die beim Anzeigen automatisch ausgef&uuml;hrt wird, dass die XAML-Definition umgesetzt, der <b>DataContext <\/b>auf die aktuelle Code behind-Klasse gesetzt und die Eigenschaft <b>_Kunden <\/b>mit dem Ergebnis der Funktion <b>GetKunden <\/b>gef&uuml;llt wird:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>New()\r\n     InitializeComponent()\r\n     DataContext = Me\r\n     _Kunden = GetKunden()\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Fenster mit ListView-Steuerelement<\/h2>\n<p>Danach definieren wir den XAML-Code f&uuml;r das Fenster zur Anzeige der Daten im <b>ListView<\/b>-Steuerelement:<\/p>\n<pre>&lt;Window x:Class=\"MainWindow\" ...\r\n         Title=\"MainWindow\" Height=\"450\" Width=\"800\" WindowStartupLocation=\"CenterScreen\"&gt;\r\n     ...\r\n     &lt;Grid&gt;\r\n         ...\r\n         &lt;ListView x:Name=\"lvw\" ItemsSource=\"{Binding Kunden}\"&gt;\r\n             &lt;ListView.View&gt;\r\n                 &lt;GridView&gt;\r\n                     &lt;GridViewColumn Header=\"ID\" DisplayMemberBinding=\"{Binding ID}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Firma\" DisplayMemberBinding=\"{Binding Firma}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Vorname\" DisplayMemberBinding=\"{Binding Vorname}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Nachname\" DisplayMemberBinding=\"{Binding Nachname}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Anrede\" DisplayMemberBinding=\"{Binding Anrede}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Strasse\" DisplayMemberBinding=\"{Binding Strasse}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"PLZ\" DisplayMemberBinding=\"{Binding PLZ}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Ort\" DisplayMemberBinding=\"{Binding Ort}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Land\" DisplayMemberBinding=\"{Binding Land}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"EMail\" DisplayMemberBinding=\"{Binding EMail}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Geburtsdatum\"                         DisplayMemberBinding=\"{Binding Path=Geburtsdatum, StringFormat=''dd.MM.yyyy''}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Alter\" DisplayMemberBinding=\"{Binding Alter}\" \/&gt;\r\n                     &lt;GridViewColumn Header=\"Newsletter\"&gt;\r\n                         &lt;GridViewColumn.CellTemplate&gt;\r\n                             &lt;DataTemplate&gt;\r\n                                 &lt;CheckBox IsChecked=\"{Binding Newsletter}\" \/&gt;\r\n                             &lt;\/DataTemplate&gt;\r\n                         &lt;\/GridViewColumn.CellTemplate&gt;\r\n                     &lt;\/GridViewColumn&gt;\r\n                 &lt;\/GridView&gt;\r\n             &lt;\/ListView.View&gt;\r\n         &lt;\/ListView&gt;\r\n         &lt;StackPanel Orientation=\"Horizontal\" Grid.Row=\"1\"&gt;\r\n             &lt;Button&gt;Button&lt;\/Button&gt;\r\n         &lt;\/StackPanel&gt;\r\n     &lt;\/Grid&gt;\r\n&lt;\/Window&gt;<\/pre>\n<p>Das <b>ListView<\/b>-Steuerelement stellen wir mit dem Attribut <b>ItemsSource <\/b>so ein, dass es den Wert der Eigenschaft <b>Kunden <\/b>als Datenquelle verwendet. Diese wird in der Code behind-Klasse wie oben beschrieben definiert. Die einzelnen Spalten im <b>ListView<\/b>-Steuerelement definieren wir als <b>GridViewColumn<\/b>-Elemente. Dabei geben wir mit dem Attribut <b>Header <\/b>die Spalten&uuml;berschrift an und mit <b>DisplayMemberBinding <\/b>das Feld, aus der die Spalte ihre Daten beziehen soll. Hier verwenden wir meist den Wert <b>{Binding [Feldname]}<\/b>, wobei <b>[Feldname] <\/b>durch den jeweiligen Feldnamen ersetzt wird. Bei zwei Feldern gibt es Abweichungen von dieser Vorgehensweise: Beim Feld <b>Geburtsdatum <\/b>verwenden wir den Ausdruck <b>{Binding Path=Geburtsdatum, StringFormat=&#8221;dd.MM.yyyy&#8221;}<\/b>, um den Inhalt des Feldes <b>Geburtsdatum <\/b>entsprechend zu formatieren. Und im Falle des Feldes <b>Newsletter<\/b>, das den Datentyp <b>Boolean <\/b>hat, wollen wir den Inhalt in einem Kontrollk&auml;stchen anzeigen. Dazu ben&ouml;tigen wir eine etwas andere Struktur, die ein <b>CheckBox<\/b>-Steuerelement enth&auml;lt, dessen Attribut <b>Checked <\/b>an das Feld <b>Newsletter <\/b>gebunden ist. Anschlie&szlig;end sieht das Fenster nach dem Starten der Anwendung wie in Bild 1 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_279_001.png\" alt=\"Die Liste der Kunden im ListView-Steuerelement\" width=\"700\" height=\"289,813\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Die Liste der Kunden im ListView-Steuerelement<\/span><\/b><\/p>\n<h2>Grundlagen zum Filtern, Sortieren und Gruppieren<\/h2>\n<p>WPF stellt die Infrastruktur zum Filtern, Sortieren und Gruppieren von Daten, die in einem Steuerelement wie beispielsweise dem <b>ListView<\/b>-Steuerelement angezeigt werden, zur Verf&uuml;gung. Dazu muss man wissen, dass das jeweilige Listen-Steuerelement nicht direkt an die Daten gebunden wird, die es anzeigen soll, sondern an eine View auf diese Daten. Diese View hat bei der in unserem Beispiel verwendeten Auflistung auf Basis der Schnittstelle <b>IList <\/b>den Typ <b>ListCollectionView<\/b>. Diese <b>ListCollectionView <\/b>bietet verschiedene Eigenschaften, die wir nutzen k&ouml;nnen &#8211; im Folgenden verwenden wir zun&auml;chst diese beiden:<\/p>\n<ul>\n<li><b>Refresh<\/b>: Aktualisiert die Ansicht mit den aktuell angegebenen Filter-, Sortierungs- und Gruppierungseinstellungen<\/li>\n<li><b>Filter<\/b>: Stellt ein, welche Funktion beim Aktualisieren zum Filtern verwendet werden soll<\/li>\n<\/ul>\n<p>Um die <b>ListCollectionView <\/b>f&uuml;r unsere Zwecke zu nutzen, machen wir diese zun&auml;chst per Variable zugreifbar:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>objListCollectionView<span style=\"color:blue;\"> As <\/span>ListCollectionView<\/pre>\n<p>Diese Variable f&uuml;llen wir gleich in der Konstruktor-Methode des Code behind-Moduls, indem wir die Methode <b>GetDefaultView <\/b>der <b>CollectionViewSource<\/b>-Klasse aufrufen und dieser einen Verweis auf die Liste &uuml;bergeben, deren <b>ListCollectionView<\/b>-Element wir erhalten wollen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>New()\r\n     ...\r\n     objListCollectionView = CollectionViewSource.GetDefaultView(Kunden)<\/pre>\n<p>In der gleichen Methode stellen wir die Eigenschaft <b>Filter <\/b>von <b>objListCollectionView <\/b>ein, und zwar auf die Funktion <b>KundenFilter<\/b>, die wir mit <b>AddressOf <\/b>angeben:<\/p>\n<pre>     objListCollectionView.Filter = AddressOf KundenFilter\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Bevor wir fortsetzen, f&uuml;gen wir dem XAML-Code f&uuml;r unser Fenster ein <b>StackPanel <\/b>hinzu, dass ein <b>Label<\/b>-, ein <b>TextBox<\/b>&#8211; und ein <b>Button<\/b>-Element enth&auml;lt:<\/p>\n<pre>&lt;StackPanel Orientation=\"Horizontal\"&gt;\r\n     &lt;Label&gt;Nachname:&lt;\/Label&gt;\r\n     &lt;TextBox x:Name=\"txtFilterNachname\" Width=\"100\"&gt;&lt;\/TextBox&gt;\r\n     &lt;Button x:Name=\"btnFiltern\" IsDefault=\"True\" Click=\"btnFiltern_Click\"&gt;Filtern&lt;\/Button&gt;\r\n&lt;\/StackPanel&gt;<\/pre>\n<p>Das <b>TextBox<\/b>-Element soll den Filterausdruck entgegennehmen, das <b>Button<\/b>-Element soll das Filtern ausl&ouml;sen. Deshalb geben wir daf&uuml;r eine Ereignismethode an, die wie folgt aussieht und lediglich die <b>Refresh<\/b>-Methode von <b>objListCollectionView <\/b>ausl&ouml;st:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>btnFiltern_Click(sender<span style=\"color:blue;\"> As Object<\/span>, e<span style=\"color:blue;\"> As <\/span>RoutedEventArgs)\r\n     objListCollectionView.Refresh()\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000279\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000279?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000279\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"123b777de9\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Daten aus einer SQL Server-Datenbank oder anderen Datenquellen k&ouml;nnen wir &uuml;ber das Entity Frame-work als Objekte zug&auml;nglich machen und auch als solche in Listen-Steuerelementen anzeigen. Aber wie sieht es mit weiteren Funktionen aus &#8211; etwa zum Filtern, Sortieren oder Gruppieren Dazu ben&ouml;tigen wir einige spezielle Techniken, von denen wir die zum Filtern von Daten nach bestimmten Kriterien im vorliegenden Artikel vorstellen. Dabei nutzen wir Filter f&uuml;r Felder mit verschiedenen Datentypen und in verschiedenen Kombinationen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662021,66042021,44000002,44000028],"tags":[],"yst_prominent_words":[],"class_list":["post-55000279","post","type-post","status-publish","format-standard","hentry","category-662021","category-66042021","category-Benutzeroberflaeche_mit_WPF","category-Word_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000279"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000279\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000279"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000279"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000279"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}