{"id":55000223,"date":"2020-06-01T00:00:00","date_gmt":"2020-09-17T16:41:17","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=223"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Rechnungsverwaltung_Teil_2_Rechnungspositionen","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Rechnungsverwaltung_Teil_2_Rechnungspositionen\/","title":{"rendered":"Rechnungsverwaltung, Teil 2: Rechnungspositionen"},"content":{"rendered":"<p><b>Als selbst&auml;ndiger oder freiberuflicher Softwareentwickler braucht man am Ende vor allem eines: eine Anwendung zum Erstellen von Rechnungen. Diese wollen wir im vorliegenden Artikel programmieren &#8211; vom Entwurf des Datenmodells &uuml;ber die Erstellung des Entity Data Models und die Benutzeroberfl&auml;che bis zum Ausdrucken der Rechnung als PDF oder mit dem Drucker. Im zweiten Teil der Beitragsreihe f&uuml;gen wir die Verwaltung von Rechnungspositionen hinzu.<\/b><\/p>\n<p><b>Vor&uuml;berlegungen<\/b><\/p>\n<p>Wenn wir unter Access Rechnungen und Rechnungspositionen verwalten wollten, war das sehr einfach m&ouml;glich &#8211; mit einem Haupt- und einem Unterformular. Einzige Bedingung war, dass der Benutzer den neuen, leeren Datensatz im Hauptformular bereits bearbeitet hatte, damit dieser einen Autowert f&uuml;r sein Prim&auml;rschl&uuml;sselfeld erhalten hat. Damit konnte man dann im Unterformular, dessen Datens&auml;tze &uuml;ber das Fremdschl&uuml;sselfeld mit dem entsprechenden Datensatz im Hauptformular verkn&uuml;pft waren, direkt die Bestellpositionen eingeben.<\/p>\n<p>Unter .NET mit WPF und dem Entity Framework ist das ein wenig aufwendiger. In diesem Beispiel wollen wir es so gestalten, dass wir ein Listenfeld zur Anzeige der vorhandenen Rechnungspositionen verwenden, die jeweils zusammen mit den Rechnungsdetails angezeigt werden. Das sieht in der Entwurfsansicht zun&auml;chst wie in Bild 1 aus. Von hier aus wollen wir ein weiteres Fenster zur Eingabe von Rechnungspositionen &ouml;ffnen. Dieses enth&auml;lt dann jeweils die Daten einer Rechnungsposition. Da diese an eine Rechnung gebunden sein muss, ben&ouml;tigen wir vor dem Speichern einer Rechnungsposition ein Rechnungsobjekt, mit dem diese Rechnung verkn&uuml;pft ist oder zumindest den Prim&auml;rschl&uuml;sselwert dieser Rechnung. Anderenfalls k&ouml;nnen wir die Rechnungsposition nicht speichern, da das Fremdschl&uuml;sselfeld zum Referenzieren der Rechnung nicht gef&uuml;llt w&auml;re.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_03\/pic_223_013.png\" alt=\"Erweiterung der Seite zur Anzeige der Rechnungsdetails\" width=\"700\" height=\"316,8979\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Erweiterung der Seite zur Anzeige der Rechnungsdetails<\/span><\/b><\/p>\n<p>Bei Access reichte es aus ein Feld eines Datensatzes mit einem Wert zu f&uuml;llen, um die Vergabe eines Autowerts f&uuml;r das Prim&auml;rschl&uuml;sselfeld auszul&ouml;sen. Bei dem darauf folgenden Wechsel in das Unterformular, wurde dieser Datensatz automatisch gespeichert und der Prim&auml;rschl&uuml;ssel stand ab sofort als Fremdschl&uuml;ssel f&uuml;r die Anlage der untergeordneten Datens&auml;tze zur Verf&uuml;gung. Unter WPF existiert dieser Automatismus nicht, weshalb wir das gew&uuml;nschte Verhalten selber entwickeln m&uuml;ssen.<\/p>\n<p>Wir haben unter anderem die folgenden M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Hinzuf&uuml;gen einer Schaltfl&auml;che, mit welcher der Benutzer den Datensatz manuell speichern kann und damit die Steuer-elemente zum Bearbeiten der Rechnungspositionen freigibt,<\/li>\n<li>automatisches Speichern der Rechnungsdaten, wenn der Benutzer die Schaltfl&auml;che zum Anlegen einer Rechnungsposition bet&auml;tigt.<\/li>\n<\/ul>\n<p>Beides ist ohnehin an die Validierung gebunden: Bevor der Rechnungsdatensatz nicht vollst&auml;ndig gef&uuml;llt wurde, kann dieser nicht gespeichert werden. Das bedeutet, dass wir auch die Freigabe der Schaltfl&auml;che zum Anlegen einer neuen Position an das vollst&auml;ndige Ausf&uuml;llen der Rechnungsdaten binden k&ouml;nnen.<\/p>\n<p>Wir wollen den zweiten Weg gehen und das Erstellen der ersten Rechnungsposition erst dann freigeben, wenn der Benutzer alle Rechnungsdaten eingegeben hat &#8211; und den Rechnungsdatensatz dann automatisch speichern. Mehr dazu weiter unten &#8211; erst folgen noch ein paar Vorbereitungen.<\/p>\n<p><b>Berechnete Felder vorbereiten<\/b><\/p>\n<p>Wir wollen f&uuml;r die Rechnungspositionen sowohl den Bruttobetrag des Einzelpreises sowie den gesamten Bruttobetrag ausgeben. Dazu ben&ouml;tigen wir zwei berechnete Felder namens <b>Brutto <\/b>und <b>BruttoGesamt<\/b>. Diese beiden Felder stecken nicht in den zugrunde liegenden Tabellen, sondern sie sollen ausschlie&szlig;lich in der Anwendung berechnet werden.<\/p>\n<p>Dazu k&ouml;nnten wir einfach der Klasse <b>Rechnungsposition <\/b>zwei Eigenschaften hinzuf&uuml;gen, welche die Werte auf Basis der Felder <b>Netto<\/b>, <b>Mehrwertsteuersatz <\/b>und <b>Menge <\/b>ermittelt. Allerdings kann es immer mal passieren, dass wir das Datenmodell &auml;ndern und die Klassen auf das neue Datenmodell anpassen wollen. Wenn wir das nicht von Hand erledigen, sondern beispielsweise auf Basis des Access-Datenmodells, wie wir es im ersten Teil der Artikelreihe verwendet haben, werden manuelle &Auml;nderungen an den Entit&auml;tsklassen jedes Mal &uuml;berschrieben. Also nutzen wir die M&ouml;glichkeit, partielle Klassen anzulegen und erstellen eine neue Klasse namens <b>Rechnungsposition_Calc<\/b>. Diese erh&auml;lt den folgenden Code:<\/p>\n<pre>Partial Public Class Rechnungsposition\r\n     Implements INotifyPropertyChanged\r\n     <span style=\"color:blue;\">Public <\/span>ReadOnly Property Brutto<span style=\"color:blue;\"> As <\/span>System.Decimal\r\n         Get\r\n             Return _Netto * (1 + _Mehrwertsteuersatz \/ 100)\r\n         End Get\r\n     End Property\r\n     <span style=\"color:blue;\">Public <\/span>ReadOnly Property BruttoGesamt<span style=\"color:blue;\"> As <\/span>System.Decimal\r\n         Get\r\n             Return _Netto * (1 + _Mehrwertsteuersatz \/ 100) * Menge\r\n         End Get\r\n     End Property\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Die <b>Property<\/b>-Eigenschaften unterscheiden sich in verschiedenen Punkten von denen, die wir in der Klasse <b>Rechnungsposition.vb <\/b>vorfinden:<\/p>\n<ul>\n<li>Sie liefern nicht die Werte von Feldern der zugrunde liegenden Tabellen zur&uuml;ck, sondern berechnete Felder auf Basis mehrerer Tabellenfelder.<\/li>\n<li>Sie weisen nur eine <b>Get<\/b>-Property, aber keine <b>Set<\/b>-Property auf. Das ist logisch, denn sie sollen ja nicht vom Benutzer eingestellt werden k&ouml;nnen, sondern werden nur berechnet.<\/li>\n<li>Da sie nur Werte zur&uuml;ckliefern, m&uuml;ssen wir das Schl&uuml;sselwort <b>ReadOnly <\/b>verwenden.<\/li>\n<\/ul>\n<p>Die Eigenschaft <b>Brutto <\/b>ermitteln wir als das Produkt des Nettopreises mit dem Wert <b>1 <\/b>plus dem Prozentsatz aus <b>Mehrwertsteuersatz <\/b>geteilt durch <b>100<\/b>. F&uuml;r die Eigenschaft <b>BruttoGesamt <\/b>multiplizieren wir dies noch mit dem Wert des Feldes <b>Menge<\/b>.<\/p>\n<p><b>Aktualisieren der Felder, wenn die zugrunde liegenden Felder aktualisiert werden<\/b><\/p>\n<p>Die Implementierung der Schnittstelle <b>INotifyPropertyChanged <\/b>sorgt in den Entit&auml;tsklassen daf&uuml;r, dass Steuer-elemente, die an Felder dieser Klassen gebunden sind, bei &Auml;nderungen der Feldinhalte automatisch aktualisiert werden. Das ist bei den berechneten Eigenschaften nicht der Fall, da diese ja keine <b>Set<\/b>-Property und damit auch keine M&ouml;glichkeit f&uuml;r den Einbau des Aufrufs von <b>OnPropertyChanged <\/b>bieten.<\/p>\n<p>Hier m&uuml;ssen wir nun doch noch in den Code der automatisch generierten Entit&auml;tsklassen eingreifen. Wir f&uuml;gen den Eigenschaften, auf denen die berechneten Eigenschaften basieren, Aufrufe der Methode <b>OnPropertyChanged <\/b>hinzu, welche nicht nur die Eigenschaft selbst, sondern auch die berechneten Eigenschaften aktualisieren, die auf dieser Eigenschaft aufbauen:<\/p>\n<pre><span style=\"color:blue;\">Public Property <\/span>Netto<span style=\"color:blue;\"> As <\/span>System.Decimal\r\n     Get\r\n         Return _Netto\r\n     End Get\r\n     <span style=\"color:blue;\">Set<\/span>\r\n         _Netto = Value\r\n         OnPropertyChanged(\"Netto\")\r\n         OnPropertyChanged(\"Brutto\")\r\n         OnPropertyChanged(\"BruttoGesamt\")\r\n     End <span style=\"color:blue;\">Set<\/span>\r\n<span style=\"color:blue;\">End Property<\/span> <\/pre>\n<p>Auf die gleiche Weise erweitern wir auch die <b>Property Set<\/b>-Eigenschaften <b>Menge <\/b>und <b>Mehrwertsteuersatz<\/b>. Das Ergebnis: Textfelder, welche die berechneten Felder <b>Brutto <\/b>und <b>BruttoGesamt <\/b>anzeigen, werden nun bei &Auml;nderung der Werte der Felder <b>Netto<\/b>, <b>Anzahl <\/b>und <b>Mehrwertsteuersatz <\/b>ebenfalls aktualisiert. Wenn Sie tats&auml;chlich einmal das Datenmodell &auml;ndern und die Entit&auml;tsklassen neu generieren lassen, m&uuml;ssen Sie diese Aufrufe von <b>OnPropertyChanged <\/b>manuell wiederherstellen.<\/p>\n<p><b>Steuer-elemente zum Verwalten der Rechnungspositionen<\/b><\/p>\n<p>Zum Verwalten der Rechnungspositionen wollen wir folgende Steuer-elemente hinzuf&uuml;gen:<\/p>\n<ul>\n<li>Listenfeld zur Anzeige der vorhandenen Rechnungspositionen<\/li>\n<li>Schaltfl&auml;che zum Hinzuf&uuml;gen einer Rechnungsposition<\/li>\n<li>Schaltfl&auml;che zum L&ouml;schen einer Rechnungsposition<\/li>\n<li>Schaltfl&auml;che zum Bearbeiten der aktuell markierten Rechnungsposition<\/li>\n<\/ul>\n<p>Au&szlig;erdem soll das Listenfeld per Doppelklick auf einen Eintrag erlauben, die Rechnungsposition zu bearbeiten.<\/p>\n<p>Zum Anlegen und Bearbeiten einer Rechnungsposition soll ein Popup-Fenster mit den Details der Rechnungsposition ge&ouml;ffnet werden. Dieses nennen wir <b>RechnungspositionDetail.xaml<\/b>, das im Entwurf wie in Bild 2 aussehen soll.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_03\/pic_223_002.png\" alt=\"Entwurf des Fensters zur Eingabe einer Rechnungsposition\" width=\"499,6607\" height=\"310,0964\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Entwurf des Fensters zur Eingabe einer Rechnungsposition<\/span><\/b><\/p>\n<p><b>RechnungspositionDetail.xaml <\/b>wollen wir nicht als Seite, sondern als Fenster anlegen. Auf diese Weise ist das Hauptfenster mit der Rechnung, f&uuml;r die Rechnungspositionen angelegt werden sollen, immer noch sichtbar und der Benutzer kann pr&uuml;fen, welche Rechnungspositionen er bereits angelegt hat.<\/p>\n<p>Damit das Fenster in der Mitte angezeigt wird und nicht irgendwo, stellen wir in <b>RechnungspositionenDetail.xaml <\/b>f&uuml;r das <b>Window<\/b>-Element das Attribut <b>WindowStartupLocation <\/b>auf <b>CenterScreen <\/b>ein:<\/p>\n<pre>&lt;Window x:Class=\"RechnungspositionDetail\"...\r\n         Title=\"RechnungspositionDetail\" Height=\"250\" Width=\"405\"\r\n         WindowStartupLocation=\"CenterScreen\"&gt;<\/pre>\n<p>Danach definieren wir die Zeilen und Spalten des Grids:<\/p>\n<pre>     &lt;Grid&gt;\r\n         &lt;Grid.ColumnDefinitions&gt;\r\n             &lt;ColumnDefinition Width=\"Auto\"&gt;&lt;\/ColumnDefinition&gt;\r\n             ... weitere Spalten\r\n             &lt;ColumnDefinition Width=\"*\"&gt;&lt;\/ColumnDefinition&gt;\r\n         &lt;\/Grid.ColumnDefinitions&gt;\r\n         &lt;Grid.RowDefinitions&gt;\r\n             &lt;RowDefinition Height=\"Auto\"&gt;&lt;\/RowDefinition&gt;\r\n             ... weitere Zeilen\r\n             &lt;RowDefinition Height=\"*\"&gt;&lt;\/RowDefinition&gt;\r\n         &lt;\/Grid.RowDefinitions&gt;<\/pre>\n<p>Die Steuer-elemente, hier ausschlie&szlig;lich Textfelder, binden wir an Elemente des Objekts <b>Rechnungsposition<\/b> und stellen ein entsprechendes Label-Steuerelement voran:<\/p>\n<pre>         &lt;Label&gt;Bezeichnung:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtBezeichnung\" Width=\"300\" Grid.Column=\"1\" Text=\"{Binding Rechnungsposition.Bezeichnung, Mode=TwoWay, ValidatesOnDataErrors=True}\"&gt;&lt;\/TextBox&gt;<\/pre>\n<p>F&uuml;r das Feld <b>Netto <\/b>legen wir das Format mit <b>StringFormat=C <\/b>fest und sorgen so f&uuml;r die Anzeige des Betrags mit Euro-Zeichen:<\/p>\n<pre>         &lt;Label Grid.Row=\"1\"&gt;Netto:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtNetto\" Width=\"100\" Grid.Row=\"1\" Grid.Column=\"1\" Text=\"{Binding Rechnungsposition.Netto,             StringFormat=C, Mode=TwoWay, ValidatesOnDataErrors=True}\"&gt;&lt;\/TextBox&gt;<\/pre>\n<p>Abh&auml;ngig von den L&auml;ndereinstellungen taucht hier dennoch das Dollar-Zeichen als W&auml;hrungssymbol auf. Um dies zu &auml;ndern, f&uuml;gen Sie der Anwendung f&uuml;r die Datei <b>Application.xaml.vb <\/b>die folgende Methode hinzu, die beim Starten der Anwendung aufgerufen wird. Au&szlig;erdem ben&ouml;tigen wir dazu die folgenden beiden <b>Namespace<\/b>-Verweise:<\/p>\n<pre>Imports System.Globalization\r\nImports System.Windows.Markup\r\n<span style=\"color:blue;\">Class<\/span> Application\r\n     Protected Overrides Sub OnStartup(ByVal e<span style=\"color:blue;\"> As <\/span>StartupEventArgs)\r\n         FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement),             <span style=\"color:blue;\">New<\/span> FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)))\r\n         MyBase.OnStartup(e)\r\n     End Sub\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Das Feld <b>Menge <\/b>ben&ouml;tigt keine weitere Formatierung:<\/p>\n<pre>         &lt;Label Grid.Row=\"2\"&gt;Menge:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtMenge\" Width=\"100\" Grid.Row=\"2\" Grid.Column=\"1\"             Text=\"{Binding Rechnungsposition.Menge, Mode=TwoWay, ValidatesOnDataErrors=True}\"&gt;&lt;\/TextBox&gt;<\/pre>\n<p>F&uuml;r das Feld <b>Mehrwertsteuersatz <\/b>definieren wir das Format mit <b>StringFormat={}{0} %<\/b>. Die vorgegebenen Formate multiplizieren den Wert jeweils mit 100. Sie m&uuml;ssten also die Prozentzahl f&uuml;r 1% mit 0,01 angeben. Das w&auml;re korrekt und lie&szlig;e sich ebenfalls abbilden, aber hier w&auml;hlen wir die einfachere Variante &#8211; wir m&uuml;ssen dies nur beim Berechnen des Brutto-Preises ber&uuml;cksichtigen, was wir oben in den berechneten Feldern bereits erledigt haben:<\/p>\n<pre>         &lt;Label Grid.Row=\"3\"&gt;MwSt:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtMehrwertsteuersatz\" Width=\"100\" Grid.Row=\"3\" Grid.Column=\"1\"             Text=\"{Binding Rechnungsposition.Mehrwertsteuersatz, StringFormat={}{0} %, Mode=TwoWay, ValidatesOnDataErrors=True}\"&gt;&lt;\/TextBox&gt;<\/pre>\n<p>Die beiden Felder <b>Brutto <\/b>und <b>BruttoGesamt <\/b>sind die berechneten Felder. Damit der Benutzer diese Werte nicht direkt &auml;ndern kann, deaktivieren wir die entsprechenden Textfelder durch Einstellen des Attributs <b>IsEnabled <\/b>auf den Wert <b>False<\/b>. Davon abgesehen greifen wir wie &uuml;blich auf die Felder <b>Brutto <\/b>und <b>BruttoGesamt <\/b>zu:<\/p>\n<pre>         &lt;Label Grid.Row=\"4\"&gt;Brutto:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtBrutto\" Grid.Row=\"4\" Width=\"100\" Grid.Column=\"1\" IsEnabled=\"False\"             Text=\"{Binding Rechnungsposition.Brutto, Mode=OneWay, StringFormat=C}\"&gt;&lt;\/TextBox&gt;\r\n         &lt;Label Grid.Row=\"5\"&gt;Brutto gesamt:&lt;\/Label&gt;\r\n         &lt;TextBox x:Name=\"txtBruttoGesamt\" Grid.Row=\"5\" Width=\"100\" Grid.Column=\"1\" IsEnabled=\"False\"             Text=\"{Binding Rechnungsposition.BruttoGesamt, Mode=OneWay, StringFormat=C}\"&gt;&lt;\/TextBox&gt;<\/pre>\n<p>Die beiden Schaltfl&auml;chen zum Speichern und Verwerfen fassen wir in ein <b>StackPanel<\/b>-Element ein. Die Schaltfl&auml;che <b>btnSpeichern <\/b>soll nur aktiviert werden, wenn die Validierungen f&uuml;r die einzugebenden gebundenen Felder erfolgreich sind. Daher f&uuml;gen wir wieder einen DataTrigger hinzu, der die Validierung der Felder <b>txtBezeichnung<\/b>, <b>txtNetto<\/b>, <b>txtMenge <\/b>und <b>txtMehrwertsteuer <\/b>durchf&uuml;hrt und im Falle auch nur eines negativen Ergebnisses die Schaltfl&auml;che <b>btnSpeichern <\/b>deaktiviert:<\/p>\n<pre>         &lt;StackPanel Orientation=\"Horizontal\" Grid.Row=\"6\" Grid.ColumnSpan=\"4\"&gt;\r\n             &lt;Button x:Name=\"btnSpeichern\" Click=\"btnSpeichern_Click\" Content=\"Speichern\"&gt;\r\n                 &lt;Button.Style&gt;\r\n                     &lt;Style TargetType=\"{x:Type Button}\" BasedOn=\"{StaticResource {x:Type Button}}\"&gt;\r\n                         &lt;Style.Triggers&gt;\r\n                             &lt;DataTrigger Binding=\"{Binding ElementName=txtBezeichnung,                                     Path=(Validation.HasError)}\" Value=\"True\"&gt;\r\n                                 &lt;Setter Property=\"IsEnabled\" Value=\"False\"&gt;&lt;\/Setter&gt;\r\n                             &lt;\/DataTrigger&gt;\r\n                             &lt;DataTrigger Binding=\"{Binding ElementName=txtNetto,                                     Path=(Validation.HasError)}\" Value=\"True\"&gt;\r\n                                 &lt;Setter Property=\"IsEnabled\" Value=\"False\"&gt;&lt;\/Setter&gt;\r\n                             &lt;\/DataTrigger&gt;\r\n                             &lt;DataTrigger Binding=\"{Binding ElementName=txtMenge,                                     Path=(Validation.HasError)}\" Value=\"True\"&gt;\r\n                                 &lt;Setter Property=\"IsEnabled\" Value=\"False\"&gt;&lt;\/Setter&gt;\r\n                             &lt;\/DataTrigger&gt;\r\n                             &lt;DataTrigger Binding=\"{Binding ElementName=txtMehrwertsteuer,                                     Path=(Validation.HasError)}\" Value=\"True\"&gt;\r\n                                 &lt;Setter Property=\"IsEnabled\" Value=\"False\"&gt;&lt;\/Setter&gt;\r\n                             &lt;\/DataTrigger&gt;\r\n                         &lt;\/Style.Triggers&gt;\r\n                     &lt;\/Style&gt;\r\n                 &lt;\/Button.Style&gt;\r\n             &lt;\/Button&gt;\r\n             &lt;Button x:Name=\"btnVerwerfen\" Click=\"btnVerwerfen_Click\" Content=\"Verwerfen\"&gt;&lt;\/Button&gt;\r\n         &lt;\/StackPanel&gt;\r\n     &lt;\/Grid&gt;\r\n&lt;\/Window&gt;<\/pre>\n<p><b>Code des Fensters RechnungspositionDetail.xaml<\/b><\/p>\n<p>Der gr&ouml;&szlig;te Teil der Funktionen des Fensters wird &uuml;ber die XAML-Definitionen abgedeckt. So bleibt noch das F&uuml;llen der anzuzeigenden oder neuen Rechnungsposition. Die daf&uuml;r notwendigen Elemente werden oben in der Klasse deklariert:<\/p>\n<pre>Imports System.ComponentModel\r\n<span style=\"color:blue;\">Public Class<\/span> RechnungspositionDetail\r\n     <span style=\"color:blue;\">Private <\/span>dbContext<span style=\"color:blue;\"> As <\/span>RechnungsverwaltungContext\r\n     <span style=\"color:blue;\">Private <\/span>_rechnungsposition<span style=\"color:blue;\"> As <\/span>Rechnungsposition<\/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\/55000223\/\">\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\/55000223?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\/55000223\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"cfdc340e0d\"\/>\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>Als selbst&auml;ndiger oder freiberuflicher Softwareentwickler braucht man am Ende vor allem eines: eine Anwendung zum Erstellen von Rechnungen. Diese wollen wir im vorliegenden Artikel programmieren &#8211; vom Entwurf des Datenmodells &uuml;ber die Erstellung des Entity Data Models und die Benutzeroberfl&auml;che bis zum Ausdrucken der Rechnung als PDF oder mit dem Drucker. Im zweiten Teil der Beitragsreihe f&uuml;gen wir die Verwaltung von Rechnungspositionen hinzu.<\/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":[662020,66032020,44000004],"tags":[],"yst_prominent_words":[],"class_list":["post-55000223","post","type-post","status-publish","format-standard","hentry","category-662020","category-66032020","category-Loesungen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000223","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=55000223"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000223\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000223"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}