{"id":55000068,"date":"2016-12-01T00:00:00","date_gmt":"2020-03-27T19:24:02","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=68"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"EDM_Kunden_verwalten_mit_Ribbon","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/EDM_Kunden_verwalten_mit_Ribbon\/","title":{"rendered":"EDM: Kunden verwalten mit Ribbon"},"content":{"rendered":"<p><b>Bisher haben wir in diesem Magazin nur einzelne Beispiele zur Darstellung von Daten aus Tabellen geliefert. Diesmal wollen wir einen Schritt weiter gehen: Wir erstellen eine WPF-Anwendung, die ein eigenes Ribbon enth&auml;lt und mit diesem die Steuerung einiger Funktionen zur Auflistung von Kunden sowie zum Bearbeiten, Hinzuf&uuml;gen und L&ouml;schen von Kundendatens&auml;tzen erm&ouml;glicht. Dabei nutzen wir als Container f&uuml;r die angezeigten Seiten mit der Kundenliste und den Kundendetails ein Frame-Objekt. Damit k&ouml;nnen wir, wenn mehrere Benutzer ge&ouml;ffnet sind, sogar durch die entsprechenden Seiten navigieren.<\/b><\/p>\n<p>Dabei wollen wir zun&auml;chst eine Kunden&uuml;bersicht und sp&auml;ter eine Seite zum Anlegen eines neuen Kunden &uuml;ber entsprechende Ribbon-Steuerelemente sichtbar machen. Eine weitere Schaltfl&auml;che soll den aktuell in der Kunden&uuml;bersicht markierten Kunden l&ouml;schen.<\/p>\n<p>Das hei&szlig;t, dass wir zun&auml;chst ein Ribbon im Fenster <b>MainWindow <\/b>unserer Beispielanwendung ben&ouml;tigen, das drei Schaltfl&auml;chen f&uuml;r die gew&uuml;nschte Navigation in den Kundendatens&auml;tzen und eine Schaltfl&auml;che zum Schlie&szlig;en des Fensters enth&auml;lt. Dies sollte sp&auml;ter so wie in Bild 1 aussehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_68_001.png\" alt=\"Erster Entwurf des Ribbons\" width=\"549,6265\" height=\"470,5365\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Erster Entwurf des Ribbons<\/span><\/b><\/p>\n<p>Um dies zu realisieren, legen Sie zun&auml;chst ein neues Projekt des Typs <b>Visual C#|WPF-Anwendung <\/b>namens <b>NavigationMitRibbons <\/b>an. Um die Ribbons zu definieren, ben&ouml;tigen Sie einen neuen Verweis, den Sie &uuml;ber den <b>Verweis-Manager <\/b>(Men&uuml;-Eintrag <b>Projekt|Verweise<\/b>) hinzuf&uuml;gen. Der Verweis hei&szlig;t <b>System.Windows.Controls.Ribbons<\/b>.<\/p>\n<p>Da wir dem <b>Window<\/b>-Element im Kopf ein Ribbon und darunter die Steuerelemente zur Anzeige der Artikel- und der Kunden&uuml;bersicht hinzuf&uuml;gen wollen, legen wir zun&auml;chst ein Grid mit zwei Zeilen an. Diese definieren wir wie folgt:<\/p>\n<pre>&lt;Grid.RowDefinitions&gt;\r\n     &lt;RowDefinition Height=\"Auto\"&gt;&lt;\/RowDefinition&gt;\r\n     &lt;RowDefinition&gt;&lt;\/RowDefinition&gt;\r\n&lt;\/Grid.RowDefinitions&gt;<\/pre>\n<p>Anschlie&szlig;end f&uuml;gen wir dem Grid ein <b>Ribbon<\/b>-Element mit zwei Schaltfl&auml;chen in verschiedenen Gruppen hinzu, das wir &uuml;ber das Attribut <b>Grid.Row=&#8221;0&#8243; <\/b>der ersten Ribbonzeile zuweisen (siehe Listing 1). Diesem f&uuml;gen wir ein <b>RibbonTab<\/b>-Element mit zwei <b>RibbonGroup<\/b>-Elementen hinzu. Die erste Gruppe statten wir mit drei <b>RibbonButton<\/b>-Elementen aus und die zweite mit einem <b>RibbonButton<\/b>-Element. Die Schaltfl&auml;chen versehen wir mit Attributen, die auf die jeweiligen Ereignismethoden verweisen. Au&szlig;erdem legen wir mit der Eigenschaft <b>LargeImageSource <\/b>den Namen jeweils einer Bilddatei fest, die im Ribbon f&uuml;r die jeweilige Schaltfl&auml;che angezeigt werden soll. Diese Bilder legen wir in einem Unterordner namens <b>images <\/b>im Projektmappen-Explorer ab.<\/p>\n<pre>&lt;Ribbon Name=\"rbnMain\" Title=\"Beispielribbon\" Grid.Row=\"0\"&gt;\r\n     &lt;RibbonTab Name=\"Tab1\" Header=\"Stammdaten\" KeyTip=\"A\"&gt;\r\n         &lt;RibbonGroup Header=\"Kunden\"&gt;\r\n             &lt;RibbonButton Name=\"btnKundenuebersicht\" Label=\"Kunden&uuml;bersicht\" Click=\"btnKundenuebersicht_Click\" \r\n                 LargeImageSource=\"images\\users.png\"&gt;&lt;\/RibbonButton&gt;\r\n             &lt;RibbonButton Name=\"btnNeuerKunde\" Label=\"Neuer Kunde\" Click=\"btnNeuerKunde_Click\" \r\n                 LargeImageSource=\"images\\user_add.png\"&gt;&lt;\/RibbonButton&gt;\r\n             &lt;RibbonButton Name=\"btnKundeLoeschen\" Label=\"Kunde l&ouml;schen\" Click=\"btnKundeLoeschen_Click\" \r\n                 LargeImageSource=\"images\\user_delete.png\" IsEnabled=\"false\"&gt;&lt;\/RibbonButton&gt;\r\n         &lt;\/RibbonGroup&gt;\r\n         &lt;RibbonGroup Header=\"Allgemein\"&gt;\r\n             &lt;RibbonButton Name=\"btnSchliessen\" Label=\"Schlie&szlig;en\" Click=\"btnSchliessen_Click\" \r\n                 LargeImageSource=\"images\\close.png\"&gt;&lt;\/RibbonButton&gt;\r\n         &lt;\/RibbonGroup&gt;\r\n     &lt;\/RibbonTab&gt;\r\n&lt;\/Ribbon&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Code f&uuml;r ein Ribbon mit Schaltfl&auml;chen in verschiedenen Gruppen<\/span><\/b><\/p>\n<h2>Seiten erstellen<\/h2>\n<p>Nun wollen wir die beiden Seiten erstellen, die durch einen Mausklick auf die beiden Ribbon-Eintr&auml;ge angezeigt werden sollen. Dazu legen Sie zun&auml;chst ein erstes neues <b>Page<\/b>-Element an und nennen es <b>Kundenuebersicht<\/b> (<b>Strg + Umschalt + A<\/b>, dann <b>Seite (WPF) <\/b>ausw&auml;hlen und den Namen unten angeben) &#8211; siehe Bild 2.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_68_002.png\" alt=\"Hinzuf&uuml;gen eines Page-Elements\" width=\"599,593\" height=\"337,9384\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Hinzuf&uuml;gen eines Page-Elements<\/span><\/b><\/p>\n<p>Das Ergebnis ist ein transparentes, rechteckiges Objekt, f&uuml;r das weder H&ouml;he noch Breite mit den &uuml;blichen Attributen <b>Height <\/b>oder <b>Width <\/b>festgelegt sind. Stattdessen finden wir die beiden Attribute <b>d:DesignHeight <\/b>und <b>d:DesignWidth<\/b>. Aber was sind das f&uuml;r Eigenschaften Eigenschaften, die mit <b>d: <\/b>beginnen, sind Eigenschaften f&uuml;r die Design-Ansicht, die nur die Gr&ouml;&szlig;e des <b>Page<\/b>-Elements f&uuml;r die Entwurfsansicht markieren.<\/p>\n<p>Zur Laufzeit wird das <b>Page<\/b>-Element ja ohnehin in das <b>Frame<\/b>-Element eingebettet und nimmt dessen Gr&ouml;&szlig;e an. Dementsprechend finden Sie im <b>Page<\/b>-Element die beiden Eigenschaften <b>d:DesignHeight <\/b>und <b>d:DesignWidth<\/b>. Das Attribut <b>mc:Ignorable=&#8221;d&#8221; <\/b>gibt dem Interpreter zu verstehen, dass Attribute mit f&uuml;hrendem <b>d <\/b>nicht interpretiert werden sollen:<\/p>\n<pre>&lt;Page x:Class=\"NavigationMitRibbons.Kundenuebersicht\" \r\n     ...\r\n     mc:Ignorable=\"d\" \r\n     d:DesignHeight=\"300\" d:DesignWidth=\"300\"\r\n     Title=\"Kundenuebersicht\"&gt;<\/pre>\n<h2>Datenquelle<\/h2>\n<p>Als Datenquelle f&uuml;r dieses Beispiel verwenden wir wieder die Datenbank <b>Bestellverwaltung<\/b>, die Sie bereits in weiteren Artikeln in diesem Magazin kennen gelernt haben. Dazu haben wir wieder ein Entity Data Model namens <b>BestellverwaltungEntities <\/b>angelegt.<\/p>\n<h2>Page mit Kunden f&uuml;llen<\/h2>\n<p>Damit das <b>Page<\/b>-Element die Kunden in einer entsprechenden Liste, hier in Form eines <b>DataGrid<\/b>-Elements, anzeigt, stellen wir zun&auml;chst eine entsprechende Datenquelle in Form eines <b>List<\/b>-Objekts in der Code behind-Datei <b>Kundenuebersicht.xaml.cs <\/b>zur Verf&uuml;gung, die wir innerhalb der Konstruktor-Methode der Klasse f&uuml;llen (siehe Listing 2).<\/p>\n<pre>public partial class Kundenuebersicht : Page {\r\n     BestellverwaltungEntities dbContext;\r\n     private List&lt;Kunde&gt; kunden;\r\n     public List&lt;Kunde&gt; Kunden {\r\n         get {\r\n             return kunden;\r\n         }\r\n         set {\r\n             kunden = value;\r\n         }\r\n     }\r\n     public Kundenuebersicht(int kundeID = 0) {\r\n         InitializeComponent();\r\n         dbContext = new BestellverwaltungEntities();\r\n         kunden = new List&lt;Kunde&gt;(dbContext.Kunden);\r\n         DataContext = this;\r\n         if (kundeID != 0) {\r\n             Kunde currentKunde = dbContext.Kunden.Find(kundeID);\r\n             dgKunden.SelectedItem = currentKunde;\r\n             dgKunden.ScrollIntoView(currentKunde);\r\n         }\r\n     }\r\n}<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Code behind-Datei der Page-Klasse Kundenuebersicht.xaml<\/span><\/b><\/p>\n<p>In der Konstruktor-Methode der Klasse <b>Kundenuebersicht <\/b>wird zun&auml;chst die Methode <b>InitializeComponent<\/b> ausgef&uuml;hrt, um das Fenster entsprechend der XAML-Definition aufzubauen. Danach erstellen wir das Entity Data Model-Objekt <b>dbContext <\/b>auf Basis der Klasse <b>BestellverwaltungEntities<\/b>. Die Liste <b>kunden<\/b>, die wir zuvor als privates <b>List<\/b>-Objekt deklariert haben, f&uuml;llen wir dann mit der Auflistung <b>Kunden <\/b>des <b>dbContext<\/b>-Objekts:<\/p>\n<pre>kunden = new List&lt;Kunde&gt;(dbContext.Kunden);<\/pre>\n<p>Danach weisen wir dem <b>Page<\/b>-Objekt mit der <b>DataContext<\/b>-Eigenschaft als Datenherkunft die Code behind-Klasse selbst zu. Damit die Seite nun auf die Kunden-Liste aus der Variablen <b>kunde<\/b> zugreifen kann, stellen wir diese noch mit einer &ouml;ffentlichen Variablen namens <b>Kunden<\/b> zur Verf&uuml;gung:<\/p>\n<pre>public List&lt;Kunde&gt; Kunden {\r\n     ...\r\n}<\/pre>\n<p>Desweiteren haben Sie sicher bemerkt, dass wir einen optionalen Parameter namens <b>kundeID <\/b>f&uuml;r die Konstruktormethode angelegt haben. Diese wird in der <b>if<\/b>-Bedingung interessant: Ist <b>kundeID <\/b>n&auml;mlich nicht <b>0<\/b>, was geschieht, wann immer eine Kunden-ID &uuml;bermittelt wird, dann liest die Methode den Kunden mit dieser ID in die Variable <b>currentKunde <\/b>ein. Dieser wird dann im DataGrid als aktueller Kunde markiert. Die Methode <b>ScrollIntoView<\/b> sorgt dann noch daf&uuml;r, dass dieser Datensatz auch noch in den sichtbaren Bereich verschoben wird. Letzteres ist f&uuml;r Access\/VBA-Programmierer nat&uuml;rlich ein Traum &#8211; dort waren f&uuml;r eine solche Aktion durchaus gr&ouml;&szlig;ere Verrenkungen n&ouml;tig.<\/p>\n<h2>DataGrid-Element in Page anlegen<\/h2>\n<p>Schlie&szlig;lich wollen wir ein <b>DataGrid<\/b>-Element im <b>Page<\/b>-Element anlegen, das wie in Listing 3 definiert wird. Die Seite hat ja als Datenherkunft bereits die Code behind-Klasse erhalten. Damit brauchen wir f&uuml;r das <b>DataGrid<\/b>-Element namens <b>dgKunden <\/b>nur noch das Attribut <b>ItemsSource <\/b>auf den Wert <b>{Binding Kunden} <\/b>einzustellen.<\/p>\n<pre>&lt;Page x:Class=\"Bestellverwaltung.Kundenuebersicht\" ...  xmlns:local=\"clr-namespace:Bestellverwaltung\"\r\n       mc:Ignorable=\"d\" d:DesignHeight=\"300\" d:DesignWidth=\"300\" Title=\"Kundenuebersicht\"&gt;\r\n     &lt;Grid&gt;\r\n         &lt;DataGrid x:Name=\"dgKunden\" ItemsSource=\"{Binding Kunden}\" AutoGenerateColumns=\"false\"&gt;\r\n             &lt;DataGrid.Columns&gt;\r\n                 &lt;DataGridTextColumn Binding=\"{Binding Path=ID}\" Header=\"ID\"  \/&gt;\r\n                 &lt;DataGridTextColumn Binding=\"{Binding Path=Firma}\" Header=\"Firma\" \/&gt;\r\n                 &lt;DataGridTextColumn Binding=\"{Binding Path=Vorname}\" Header=\"Vorname\"  \/&gt;\r\n                 &lt;DataGridTextColumn Binding=\"{Binding Path=Nachname}\" Header=\"Nachname\" \/&gt;\r\n             &lt;\/DataGrid.Columns&gt;\r\n         &lt;\/DataGrid&gt;\r\n     &lt;\/Grid&gt;\r\n&lt;\/Page&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Code f&uuml;r die Definition des Page-Elements zur Anzeige der Kunden&uuml;bersicht<\/span><\/b><\/p>\n<p>Es verwendet dann die Auflistung <b>Kunden <\/b>aus der Klasse <b>Kunden-uebersicht.xaml.cs <\/b>als Datenquelle. Die Spalten sollen nicht automatisch erstellt werden, daher erh&auml;lt <b>AutoGenerateColumns <\/b>den Wert <b>false<\/b>. Die Spalten legen wir unterhalb des Elements <b>DataGrid.Columns <\/b>an, und zwar als <b>DataGridTextColumn<\/b>-Elemente. Hier erhalten diese per <b>Binding <\/b>eine Verkn&uuml;pfung zum jeweiligen Feld der Datenherkunft sowie per <b>Header<\/b> eine Spalten&uuml;berschrift. Das Ergebnis soll anschlie&szlig;end wie in Bild 4 aussehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_68_003.png\" alt=\"Das Page-Element mit den Kundendaten im Frame-Element des Window-Objekts\" width=\"499,6607\" height=\"379,3901\" \/><\/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\/55000068\/\">\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\/55000068?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\/55000068\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"22c77db969\"\/>\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>Bisher haben wir in diesem Magazin nur einzelne Beispiele zur Darstellung von Daten aus Tabellen geliefert. Diesmal wollen wir einen Schritt weitergehen: Wir erstellen eine WPF-Anwendung, die ein eigenes Ribbon enth&auml;lt und mit diesem die Steuerung einiger Funktionen zur Auflistung von Kunden sowie zum Bearbeiten, Hinzuf&uuml;gen und L&ouml;schen von Kundendatens&auml;tzen erm&ouml;glicht. Dabei nutzen wir als Container f&uuml;r die angezeigten Seiten mit der Kundenliste und den Kundendetails ein Frame-Objekt. Damit k&ouml;nnen wir, wenn mehrere Benutzer ge&ouml;ffnet sind, sogar durch die entsprechenden Seiten navigieren.<\/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,66062016,44000002,44000024,44000027,44000004,44000007],"tags":[],"yst_prominent_words":[],"class_list":["post-55000068","post","type-post","status-publish","format-standard","hentry","category-662016","category-66062016","category-Benutzeroberflaeche_mit_WPF","category-Berichte_und_Reporting","category-Excel_programmieren","category-Loesungen","category-Von_Access_zu_WPF"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000068","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=55000068"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000068\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000068"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000068"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000068"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000068"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}