{"id":55000151,"date":"2018-10-01T00:00:00","date_gmt":"2020-03-27T19:34:33","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=151"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"EDM_DataGrid_als_Datenblatt","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/EDM_DataGrid_als_Datenblatt\/","title":{"rendered":"EDM: DataGrid als Datenblatt"},"content":{"rendered":"<p><b>Wer von Access kommt und Datenbankanwendungen mit Visual Studio programmieren m&ouml;chte, vermisst vermutlich das einfache Datenblatt, das man unter Access mit wenigen Mausklicks zusammenstellen konnte. Dieses zeigt nicht nur die Datens&auml;tze der als Datenherkunft verwendeten Tabelle oder Abfrage an, sondern bietet auch die M&ouml;glichkeit, die enthaltenen Daten zu &auml;ndern, zu l&ouml;schen oder durch neue Datens&auml;tze zu erg&auml;nzen. Dies wollen wir in diesem Artikel durch den Einsatz eines entsprechend programmierten DataGrid-Steuerelements nachbauen.<\/b><\/p>\n<h2>Beispieldaten<\/h2>\n<p>In den Artikeln <b>Von Access zu Entity Framework: Datenmodell <\/b>und <b>Von Access zu Entity Framework: Daten <\/b>haben wir gezeigt, wie Sie ein Entity Data Modell auf Basis eines Access-Datenmodells erstellen und die Daten f&uuml;r die daraus zu erzeugenden Tabellen in eine <b>Seed<\/b>-Methode schreiben. Im Beispielprojekt dieses Artikels haben wir das Entity Data Model und die Klasse mit der <b>Seed<\/b>-Methode bereits angelegt, sodass Sie nach dem Kopieren des Projektordners auf Ihren Rechner einfach nur den die Anweisung Update-Database in der Paket-Manager-Konsole ausf&uuml;hren m&uuml;ssen. Dadurch sollte automatisch eine Datenbank f&uuml;r den in der Verbindungszeichenfolge angegebenen SQL Server, hier <b>LocalDb<\/b>, angelegt und mit den angegebenen Tabellen und Daten gef&uuml;llt werden.<\/p>\n<h2>Fenster mit DataGrid anlegen<\/h2>\n<p>Wir wollen gleich ein eigenes Fenster f&uuml;r dieses Beispiel anlegen, das Sie dann &uuml;ber eine Schaltfl&auml;che vom Fenster <b>MainWindow <\/b>aus aufrufen k&ouml;nnen. Dazu legen wir die folgende Schaltfl&auml;che in diesem Fenster an:<\/p>\n<pre>&lt;Grid&gt;\r\n     &lt;Button x:Name=\"btnProdukteDataGrid\" Click=\"btnProdukteDataGrid_Click\"&gt;DataGrid mit Produkten&lt;\/Button&gt;\r\n&lt;\/Grid&gt;<\/pre>\n<p>Die Schaltfl&auml;che soll die folgende Ereignismethode aufrufen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>btnProdukteDataGrid_Click(sender<span style=\"color:blue;\"> As Object<\/span>, e<span style=\"color:blue;\"> As <\/span>RoutedEventArgs)\r\n     <span style=\"color:blue;\">Dim <\/span>wnd<span style=\"color:blue;\"> As <\/span>Window\r\n     wnd = <span style=\"color:blue;\">New<\/span> ProdukteDataGrid\r\n     wnd.ShowDialog()\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das neue Fenster nennen wir <b>ProdukteDatagrid.xaml<\/b>. Zun&auml;chst legen wir ein paar Elemente in der Code behind-Klasse an, der wir zun&auml;chst die Konstruktor-Methode hinzuf&uuml;gen:<\/p>\n<pre><span style=\"color:blue;\">Public Class<\/span> ProdukteDataGrid\r\n     <span style=\"color:blue;\">Public <\/span>Sub New()\r\n     End Sub\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Wir ben&ouml;tigen einen Verweis auf den Namespace <b>System.Collections.ObjectModel<\/b>:<\/p>\n<pre>Imports System.Collections.ObjectModel<\/pre>\n<p>In der Klasse definieren wir eine lokale Variable f&uuml;r die Kontextklasse sowie die Liste der Produkte:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>dbContext<span style=\"color:blue;\"> As <\/span>BestellverwaltungContext\r\n<span style=\"color:blue;\">Private <\/span>m_Produkte<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Produkt)<\/pre>\n<p>Die Liste der Produkte wollen wir &uuml;ber eine &ouml;ffentliche Eigenschaft namens <b>Produkte <\/b>verf&uuml;gbar machen:<\/p>\n<pre><span style=\"color:blue;\">Public Property <\/span>Produkte()<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Produkt)\r\n     Get\r\n         Return m_Produkte\r\n     End Get\r\n     Set(ByVal value<span style=\"color:blue;\"> As <\/span>ObservableCollection(Of Produkt))\r\n         m_Produkte = value\r\n     End <span style=\"color:blue;\">Set<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Damit das DataGrid beim &Ouml;ffnen direkt mit den Daten gef&uuml;llt wird, erweitern wir die Konstruktormethode mit diesen Anweisungen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>New()\r\n     InitializeComponent()\r\n     dbContext = <span style=\"color:blue;\">New<\/span> BestellverwaltungContext\r\n     Produkte = <span style=\"color:blue;\">New<\/span> ObservableCollection(Of Produkt)(dbContext.Produkte)\r\n     DataContext = Me\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Darin f&uuml;llen wir die Kontext-Variable und die <b>List<\/b>-Variable <b>Produkte <\/b>mit der Liste der Produkte. Schlie&szlig;lich stellen wir den <b>DataContext <\/b>auf die Code behind-Klasse ein. Wenn wir nun das Projekt starten und im Fenster <b>MainWindow<\/b> auf die Schaltfl&auml;che klicken, erscheint das DataGrid wie in Bild 1.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_05\/pic_151_001.png\" alt=\"DataGrid mit den Daten der Tabelle Produkte\" width=\"424,7115\" height=\"266,7953\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: DataGrid mit den Daten der Tabelle Produkte<\/span><\/b><\/p>\n<h2>Kombinationsfelder anzeigen<\/h2>\n<p>Die Daten der Felder <b>KategorieID <\/b>und <b>MehrwertsteuersatzID <\/b>m&ouml;chten wir gern aus den jeweils verkn&uuml;pften Auflistungen <b>Kategorien <\/b>und <b>Mehrwertsteuersaetze <\/b>f&uuml;llen. Au&szlig;erdem wollen wir noch die Spalten&uuml;berschriften anpassen. Das erledigen wir mit den folgenden Erweiterungen, wobei wir erst die Daten f&uuml;r die Kombinationsfelder in der Code behind-Klasse verf&uuml;gbar machen. Dazu f&uuml;gen wir zwei private Variablen f&uuml;r die Listen der Kategorien und der Mehrwertsteuers&auml;tze hinzu:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Kategorien<span style=\"color:blue;\"> As <\/span>List(Of Kategorie)\r\n<span style=\"color:blue;\">Private <\/span>m_Mehrwertsteuersaetze<span style=\"color:blue;\"> As <\/span>List(Of Mehrwertsteuersatz)<\/pre>\n<p>F&uuml;r beide richten wir entsprechende &ouml;ffentliche Eigenschaften ein:<\/p>\n<pre><span style=\"color:blue;\">Public Property <\/span>Kategorien<span style=\"color:blue;\"> As <\/span>List(Of Kategorie)\r\n     Get\r\n         Return m_Kategorien\r\n     End Get\r\n     Set(ByVal value<span style=\"color:blue;\"> As <\/span>List(Of Kategorie))\r\n         m_Kategorien = value\r\n     End <span style=\"color:blue;\">Set<\/span>\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property <\/span>Mehrwertsteuersaetze<span style=\"color:blue;\"> As <\/span>List(Of Mehrwertsteuersatz)\r\n     Get\r\n         Return m_Mehrwertsteuersaetze\r\n     End Get\r\n     Set(ByVal value<span style=\"color:blue;\"> As <\/span>List(Of Mehrwertsteuersatz))\r\n         m_Mehrwertsteuersaetze = 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 f&uuml;llen wir diese in der Konstruktor-Methode aus den entsprechenden DbSets:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>New()\r\n     ...\r\n     Kategorien = <span style=\"color:blue;\">New<\/span> List(Of Kategorie)(dbContext.Kategorien)\r\n     Mehrwertsteuersaetze = <span style=\"color:blue;\">New<\/span> List(Of Mehrwertsteuersatz)(dbContext.Mehrwertsteuersaetze)\r\n     DataContext = Me\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit stehen die Daten der Kategorien und der Mehrwertsteuers&auml;tze &uuml;ber die &ouml;ffentlichen Variablen <b>Kategorien <\/b>und <b>Mehrwertsteuersaetze <\/b>f&uuml;r den Zugriff aus der XAML-Seite bereit. Diese passen wir nun wie folgt an. Zun&auml;chst stellen wir <b>AutoGenerateColumns<\/b> auf <b>False <\/b>ein, da wir die Spalten nun von Hand definieren:<\/p>\n<pre>&lt;DataGrid x:Name=\"dgProdukte\" ItemsSource=\"{Binding Produkte}\" AutoGenerateColumns=\"False\"&gt;<\/pre>\n<p>Dann folgen die einzelnen Spaltendefinitionen im <b>DataGrid.Columns<\/b>-Element:<\/p>\n<pre>     &lt;DataGrid.Columns&gt;\r\n         &lt;DataGridTextColumn Binding=\"{Binding Path=Name}\" Header=\"Produkt\"&gt;&lt;\/DataGridTextColumn&gt;<\/pre>\n<p>Das Kombinationsfeld realisieren wir als <b>DataGridComboBocColumn<\/b>-Element, f&uuml;r das wir den Header festlegen sowie das gebundene Feld der Datenquelle des DataGrids beziehungsweise des Fensters (<b>SelectedValueBinding<\/b>), den Namen des anzuzeigenden Feldes (<b>DisplayMemberPath<\/b>) und den Namen des gebundenen Feldes (<b>SelectedValuePath<\/b>):<\/p>\n<pre>         &lt;DataGridComboBoxColumn Header=\"Kategorie\" SelectedValueBinding=\"{Binding KategorieID}\"             DisplayMemberPath=\"Name\" SelectedValuePath=\"ID\"&gt;<\/pre>\n<p>Die Datenquelle f&uuml;r das Kombinationsfeld m&uuml;ssen wir &uuml;ber einen Umweg festlegen, indem wir die Eigenschaft <b>ItemsSource <\/b>manuell definieren und f&uuml;llen. Die Daten beziehen wir dabei aus der entsprechenden Eigenschaft des &uuml;bergeordneten <b>Window<\/b>-Elements. Dies legen wir sowohl f&uuml;r die Eigenschaft <b>ElementStyle <\/b>als auch f&uuml;r die Eigenschaft <b>EditingElementStyle <\/b>fest. Dabei liefert <b>ElementStyle <\/b>die Formatierung f&uuml;r den angezeigten Text des Kombinationsfeldes und <b>EditingElementStyle <\/b>die Formatierung f&uuml;r die Elemente in der Liste nach dem Aufklappen:<\/p>\n<pre>             &lt;DataGridComboBoxColumn.ElementStyle&gt;\r\n                 &lt;Style TargetType=\"{x:Type ComboBox}\"&gt;\r\n                 &lt;Setter Property=\"ItemsSource\" Value=\"{Binding Path=DataContext.Kategorien,                     RelativeSource={RelativeSource AncestorType={x:Type Window}}}\" \/&gt;\r\n             &lt;\/Style&gt;\r\n             &lt;\/DataGridComboBoxColumn.ElementStyle&gt;\r\n             &lt;DataGridComboBoxColumn.EditingElementStyle&gt;\r\n                 &lt;Style TargetType=\"{x:Type ComboBox}\"&gt;\r\n                     &lt;Setter Property=\"ItemsSource\" Value=\"{Binding Path=DataContext.Kategorien,                         RelativeSource={RelativeSource AncestorType={x:Type Window}}}\" \/&gt;\r\n                 &lt;\/Style&gt;\r\n             &lt;\/DataGridComboBoxColumn.EditingElementStyle&gt;\r\n         &lt;\/DataGridComboBoxColumn&gt;<\/pre>\n<p>Beim Kombinationsfeld f&uuml;r die Mehrwertsteuers&auml;tze ist noch eine weitere Information in Form eines zus&auml;tzlichen Setters erforderlich, und zwar die Angabe der Formatierung. W&auml;hrend die Mehrwertsteuers&auml;tze in Form der Werte <b>0,07 <\/b>und <b>0,19 <\/b>gespeichert sind, sollen diese als <b>7,00% <\/b>und <b>19,00% <\/b>im Kombinationsfeld erscheinen. Daher definieren wir hier zus&auml;tzlich den Setter f&uuml;r die Eigenschaft <b>ItemStringFormat<\/b>:<\/p>\n<pre>         &lt;DataGridComboBoxColumn Header=\"MwSt.-Satz\" SelectedValueBinding=\"{Binding MehrwertsteuersatzID}\"             DisplayMemberPath=\"Name\" SelectedValuePath=\"ID\"&gt;\r\n             &lt;DataGridComboBoxColumn.ElementStyle&gt;\r\n                 &lt;Style TargetType=\"{x:Type ComboBox}\"&gt;\r\n                     &lt;Setter Property=\"ItemsSource\" Value=\"{Binding Path=DataContext.Mehrwertsteuersaetze,                         RelativeSource={RelativeSource AncestorType={x:Type Window}}}\" \/&gt;\r\n                     &lt;Setter Property=\"ItemStringFormat\" Value=\"P\"&gt;&lt;\/Setter&gt;\r\n                 &lt;\/Style&gt;\r\n             &lt;\/DataGridComboBoxColumn.ElementStyle&gt;\r\n             &lt;DataGridComboBoxColumn.EditingElementStyle&gt;\r\n                 &lt;Style TargetType=\"{x:Type ComboBox}\"&gt;\r\n                     &lt;Setter Property=\"ItemsSource\" Value=\"{Binding Path=DataContext.Mehrwertsteuersaetze,                         RelativeSource={RelativeSource AncestorType={x:Type Window}}}\" \/&gt;\r\n                     &lt;Setter Property=\"ItemStringFormat\" Value=\"P\"&gt;&lt;\/Setter&gt;\r\n                 &lt;\/Style&gt;\r\n             &lt;\/DataGridComboBoxColumn.EditingElementStyle&gt;\r\n         &lt;\/DataGridComboBoxColumn&gt;<\/pre>\n<p>Schlie&szlig;lich folgen noch die Spaltendefinitionen f&uuml;r die &uuml;brigen Felder:<\/p>\n<pre>         &lt;DataGridTextColumn Binding=\"{Binding Path=Einzelpreis}\" Header=\"Einzelpreis\"&gt;&lt;\/DataGridTextColumn&gt;\r\n         &lt;DataGridTextColumn Binding=\"{Binding Path=Bestand}\" Header=\"Bestand\"&gt;&lt;\/DataGridTextColumn&gt;\r\n         &lt;DataGridTextColumn Binding=\"{Binding Path=Mindestbestand}\" Header=\"Mindestbestand\"&gt;&lt;\/DataGridTextColumn&gt;\r\n         &lt;DataGridCheckBoxColumn Binding=\"{Binding Path=Auslaufprodukt}\" Header=\"Auslaufprodukt\"&gt;&lt;\/DataGridCheckBoxColumn&gt;\r\n     &lt;\/DataGrid.Columns&gt;\r\n&lt;\/DataGrid&gt;<\/pre>\n<p>Nach einem Neustart sieht das <b>DataGrid<\/b>-Steuerelement nun wie in Bild 2 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_05\/pic_151_002.png\" alt=\"DataGrid mit Kombinationsfeldern\" width=\"549,6265\" height=\"308,2425\" \/><\/p>\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\/55000151\/\">\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\/55000151?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\/55000151\/\"\/>\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>Wer von Access kommt und Datenbankanwendungen mit Visual Studio programmieren m&ouml;chte, vermisst vermutlich das einfache Datenblatt, das man unter Access mit wenigen Mausklicks zusammenstellen konnte. Dieses zeigt nicht nur die Datens&auml;tze der als Datenherkunft verwendeten Tabelle oder Abfrage an, sondern bietet auch die M&ouml;glichkeit, die enthaltenen Daten zu &auml;ndern, zu l&ouml;schen oder durch neue Datens&auml;tze zu erg&auml;nzen. Dies wollen wir in diesem Artikel durch den Einsatz eines entsprechend programmierten DataGrid-Steuerelements nachbauen.<\/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":[662018,66052018,44000002,44000022,44000015],"tags":[],"yst_prominent_words":[],"class_list":["post-55000151","post","type-post","status-publish","format-standard","hentry","category-662018","category-66052018","category-Benutzeroberflaeche_mit_WPF","category-Von_Access_zu_NET","category-WPFSteuerelemente"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000151","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=55000151"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000151\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000151"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000151"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000151"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000151"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}