{"id":55000059,"date":"2016-10-01T00:00:00","date_gmt":"2020-03-27T19:22:53","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=59"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"EDM_1nBeziehung_als_ParentChildAnsicht","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/EDM_1nBeziehung_als_ParentChildAnsicht\/","title":{"rendered":"EDM: 1:n-Beziehung als Parent-Child-Ansicht"},"content":{"rendered":"<p><b>Eine der unter Access ganz einfach abzubildenden Hierarchien zweier Tabellen ist die 1:n-Beziehung in einem Haupt- und einem Unterformular. Auch unter WPF mit den Daten aus einem Entity Data Model l&auml;sst sich dies gut abbilden. Wir schauen uns in diesem Artikel an, wie es funktioniert und was Sie beim Anzeigen der Daten beachten m&uuml;ssen. Als Beispiel nutzen wir die Kategorien der Datenbank im Hauptfenster und die der aktuellen Kategorie zugeordneten Artikel in einer Listenansicht.<\/b><\/p>\n<p>Als Beispiele verwenden wir die beispielsweise im Artikel <b>EDM: Einfaches Detailfenster <\/b>vorgestellten Tabellen der Datenbank namens <b>Bestellverwaltung<\/b>, in diesem Fall speziell die Tabelle <b>Kategorien <\/b>f&uuml;r das Hauptfenster, die Tabelle <b>Artikel <\/b>f&uuml;r die Liste sowie die Tabelle <b>Lieferanten <\/b>als Look-up-tabelle der Tabelle <b>Artikel<\/b> zur Auswahl der Lieferanten.<\/p>\n<h2>Hauptfenster anlegen<\/h2>\n<p>F&uuml;r das Hauptfenster f&uuml;gen Sie dem Projekt ein neues WPF-Fenster namens <b>KategorienUndArtikel <\/b>hinzu. Nun wollen wir in diesem die Kategorien in der Detailansicht anzeigen, also jeweils nur eine Kategorie gleichzeitig. Dar&uuml;ber hinaus ben&ouml;tigen wir dann nat&uuml;rlich noch Navigationsschaltfl&auml;chen.<\/p>\n<p>Da wir im Artikel <b>EDM: Einfaches Detailfenster <\/b>ja prinzipiell schon die gleiche Aufgabe erledigt haben, k&ouml;nnen wir uns dort bedienen (im Beispielprojekt finden Sie auch die in diesem Artikel behandelten Fenster). Als Erstes k&uuml;mmern wir uns um die zugrunde liegenden Daten. Dazu f&uuml;gen wir dem XAML-Code unterhalb des <b>Window<\/b>-Elements gleich die Referenz auf die Datenquelle hinzu:<\/p>\n<pre>&lt;Window.Resources&gt;\r\n     &lt;CollectionViewSource x:Key=\"vsKategorien\" \r\n         d:DesignSource=\"{d:DesignInstance {x:Type \r\n         local:Kategorie}, CreateList=True}\"\/&gt;\r\n&lt;\/Window.Resources&gt;<\/pre>\n<p>Im Code behind-Modul legen wir die Variable f&uuml;r die <b>Col-lectionViewSource <\/b>an, diesmal im Gegensatz zu den vom Visual Studio automatisch per Drag and Drop hinzugef&uuml;gten CollectionViewSources aus den anderen Beispielen mit dem Pr&auml;fix <b>vs<\/b>, also unter dem Namen <b>vsKategorien<\/b>. Au&szlig;erdem deklarieren und initialisieren wir auch hier den Datenbankkontext namens <b>DBContext <\/b>auf Basis der Klasse <b>BestellverwaltungEntities<\/b>:<\/p>\n<pre>CollectionViewSource vsKategorien;\r\nBestellverwaltungEntities DBContext = \r\n     new BestellverwaltungEntities();<\/pre>\n<p>Dann statten wir die Konstruktor-Methode, die beim Initialisieren des Fensters <b>KategorienUndArtikel <\/b>ausgel&ouml;st wird, mit ein paar zus&auml;tzlichen Anweisungen aus, die unsere <b>CollectionViewSource <\/b>mit den Daten der Entit&auml;tsliste <b>Kategorien <\/b>des <b>DBContext<\/b>-Objekts f&uuml;llen:<\/p>\n<pre>public KategorienUndArtikel() {\r\n     InitializeComponent();\r\n     vsKategorien= ((CollectionViewSource)\r\n         (this.FindResource(\"vsKategorien\")));\r\n     DBContext.Kategorien.Load();\r\n     vsKategorien.Source = DBContext.Kategorien.Local;\r\n}<\/pre>\n<p>Nun folgt die Definition der Steuerelemente im Fenster. Dazu f&uuml;gen wir dem bereits vorhandenen <b>Grid<\/b>-Element die statische Ressource von oben als <b>DataContext <\/b>hinzu:<\/p>\n<pre>&lt;Grid DataContext=\"{StaticResource vsKategorien}\"&gt;<\/pre>\n<p>Danach definieren wir f&uuml;r das Grid zwei Spalten und vier Zeilen. Die ersten beiden Spalten sollen die Felder <b>ID <\/b>und <b>Bezeichnung <\/b>der Entit&auml;t <b>Kategorie <\/b>anzeigen. Dazu stellen wir das Attribut <b>Text <\/b>auf einen entsprechenden <b>Binding<\/b>-Ausdruck ein, der die Eigenschaft <b>ID <\/b>referenziert. Gleiches erledigen wir f&uuml;r das Textfeld <b>txtBezeichnung<\/b>, welches auf die Eigenschaft <b>Bezeichnung <\/b>zeigt (siehe Listing 1).<\/p>\n<pre>&lt;Grid DataContext=\"{StaticResource vsKategorien}\"&gt;\r\n     &lt;Grid.ColumnDefinitions&gt;\r\n         &lt;ColumnDefinition Width=\"Auto\"\/&gt;\r\n         &lt;ColumnDefinition Width=\"Auto\"\/&gt;\r\n     &lt;\/Grid.ColumnDefinitions&gt;\r\n     &lt;Grid.RowDefinitions&gt;\r\n         &lt;RowDefinition Height=\"Auto\"\/&gt;\r\n         &lt;RowDefinition Height=\"Auto\"\/&gt;\r\n         &lt;RowDefinition Height=\"Auto\"\/&gt;\r\n         &lt;RowDefinition Height=\"Auto\"\/&gt;\r\n     &lt;\/Grid.RowDefinitions&gt;\r\n     &lt;Label Content=\"ID:\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" Margin=\"3\" VerticalAlignment=\"Center\"\/&gt;\r\n     &lt;TextBox x:Name=\"txtID\" Grid.Column=\"1\" HorizontalAlignment=\"Left\" Height=\"22\" Margin=\"3,4,0,6\" Text=\"{Binding ID, \r\n         Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}\" VerticalAlignment=\"Center\" Width=\"120\"\/&gt;\r\n     &lt;Label Content=\"Bezeichnung:\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" Margin=\"3\" Grid.Row=\"1\" \r\n         VerticalAlignment=\"Center\"\/&gt;\r\n     &lt;TextBox x:Name=\"txtBezeichnung\" Grid.Column=\"1\" HorizontalAlignment=\"Left\" Height=\"23\" Margin=\"3\" \r\n         Grid.Row=\"1\" Text=\"{Binding Bezeichnung, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}\" \r\n         VerticalAlignment=\"Center\" Width=\"120\"\/&gt;\r\n     ...\r\n&lt;\/Grid&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Definition der Steuerelemente des Hauptfensters<\/span><\/b><\/p>\n<p>Nun fehlen allerdings noch die Navigationsschaltfl&auml;chen. Diese k&ouml;nnen Sie einfach in einem St&uuml;ck aus dem XAML-Code des Fensters <b>ArtikelMitKombinationsfeld <\/b>als Grid in die dritte Zeile des Hauptgrids hineinkopieren. Am XAML-Code brauchen Sie keine &Auml;nderungen vorzunehmen. Das Fenster sieht nun im Entwurf wie in Bild 1 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_05\/pic_59_001.png\" alt=\"Aktuelle Entwurfsansicht des Fensters\" width=\"424,7115\" height=\"424,7115\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Aktuelle Entwurfsansicht des Fensters<\/span><\/b><\/p>\n<h2>Code f&uuml;r Navigationsschaltfl&auml;chen kopieren und anpassen<\/h2>\n<p>Danach kopieren Sie die Ereignismethoden aus der Code behind-Klasse des Fensters <b>ArtikelMitKombinationsfeld <\/b>in die Code behind-Klasse des neuen Fensters <b>KategorienUndArtikel<\/b>. Die Methoden passen Sie derart an, dass Sie den Namen der <b>CollectionViewSource <\/b>austauschen sowie an allen Stellen die Liste <b>Artikel <\/b>durch die Liste <b>Kategorien <\/b>und die Entit&auml;t <b>Artikel <\/b>durch die Entit&auml;t <b>Kategorie <\/b>ersetzen. Das Ergebnis sieht wie in Listing 2 aus. Danach k&ouml;nnen Sie das Projekt schon starten und die Datens&auml;tze des neuen Fensters mit den Navigationsschaltfl&auml;chen durchlaufen.<\/p>\n<pre>private void btnErster_Click(object sender, RoutedEventArgs e) {\r\n     Speichern();\r\n     if (vsKategorien.View.CurrentPosition &gt; 0) {\r\n         vsKategorien.View.MoveCurrentToFirst();\r\n     }\r\n}\r\nprivate void btnVorheriger_Click(object sender, RoutedEventArgs e) {\r\n     Speichern();\r\n     if (vsKategorien.View.CurrentPosition &gt; 0) {\r\n         vsKategorien.View.MoveCurrentToPrevious();\r\n     }\r\n}\r\nprivate void btnNaechster_Click(object sender, RoutedEventArgs e) {\r\n     Speichern();\r\n     if (vsKategorien.View.CurrentPosition &lt; ((CollectionView)vsKategorien.View).Count) {\r\n         vsKategorien.View.MoveCurrentToNext();\r\n     }\r\n}\r\nprivate void btnLetzter_Click(object sender, RoutedEventArgs e) {\r\n     Speichern();\r\n     if (vsKategorien.View.CurrentPosition &lt; ((CollectionView)vsKategorien.View).Count) {\r\n         vsKategorien.View.MoveCurrentToLast();\r\n     }\r\n}\r\nprivate void Speichern() {\r\n     if (DBContext.ChangeTracker.HasChanges()) {\r\n         DBContext.SaveChanges();\r\n     }\r\n}\r\nprivate void btnNeu_Click(object sender, RoutedEventArgs e) {\r\n     DBContext.Kategorien.Add(DBContext.Kategorien.Create());\r\n     vsKategorien.View.MoveCurrentToLast();\r\n}\r\nprivate void btnLoeschen_Click(object sender, RoutedEventArgs e) {\r\n     Kategorie kategorie = (Kategorie)vsKategorien.View.CurrentItem;\r\n     if (kategorie != null) {\r\n         DBContext.Kategorien.Remove(kategorie);\r\n         Speichern();\r\n     }\r\n}<\/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\/55000059\/\">\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\/55000059?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\/55000059\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"5839a24d75\"\/>\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>Eine der unter Access ganz einfach abzubildenden Hierarchien zweier Tabellen ist die 1:n-Beziehung in einem Haupt- und einem Unterformular. Auch unter WPF mit den Daten aus einem Entity Data Model l&auml;sst sich dies gut abbilden. Wir schauen uns in diesem Artikel an, wie es funktioniert und was Sie beim Anzeigen der Daten beachten m&uuml;ssen. Als Beispiel nutzen wir die Kategorien der Datenbank im Hauptfenster und die der aktuellen Kategorie zugeordneten Artikel in einer Listenansicht.<\/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":[662016,66052016,44000002,44000021,44000023,44000036],"tags":[],"yst_prominent_words":[],"class_list":["post-55000059","post","type-post","status-publish","format-standard","hentry","category-662016","category-66052016","category-Benutzeroberflaeche_mit_WPF","category-Entity_Framework","category-PowerApps","category-Ribbon_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000059","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=55000059"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000059\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000059"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}