LernMoment.deJekyll2021-09-17T16:10:06+02:00https://www.lernmoment.de/Jan Suchotzkihttps://www.lernmoment.de/jan@lernmoment.dehttps://www.lernmoment.de/alle/projekt-klonen-von-github2021-03-10T06:00:00+01:002021-03-10T06:00:00+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Seit November 2020, genauer gesagt seit Version 16.8 von Visual Studio, hat sich die Oberfläche zur Bedienung von Git grundlegende geändert. Daher sind viele Anleitungen die du im Internet findest (inkl. einiger hier auf LernMoment 🙃) nicht mehr aktuell.</p>
<p>In diesem Artikel zeige ich dir wie du ein auf GitHub bestehendes Projekt in Visual Studio auf deinen Rechner holst. Der Fachbegriff dafür ist du “klonst ein Projekt”. Damit kannst du dir beispielsweise den Quellcode eines der vielen Projekte von <a href="https://github.com/lernmoment">LernMoment auf GitHub</a> holen.</p>
<p>Bevor wir anfangen hier ein paar Dinge die du beachten solltest:</p>
<ul>
<li>Möchtest du nur den Quellcode holen, wie in diesem Aritkel beschrieben, benötigst du <strong>keinen</strong> GitHub-Account</li>
<li>In Visual Studio gibt es die <a href="https://visualstudio.github.com/">GitHub Extension for Visual Studio</a>. Diese brauchst du auch <strong>nicht</strong>, aber es schadet natürlich nicht, wenn du sie hast 😉.</li>
<li>Git und GitHub bieten viele Möglichkeiten zur Zusammenarbeit. Der hier vorgestellte Weg ist <strong>nur</strong> dafür gedacht, dass du alleine im Quellcode arbeitest. Auch kannst du Änderungen die du machst nicht einfach zurück nach GitHub schieben. (Siehe die Links am Ende dieses Artikels für andere Möglickeiten)</li>
</ul>
<p>Nun aber los …</p>
<h2 id="1---die-url-vom-projekt-finden">1 - Die URL vom Projekt finden</h2>
<p>In einigen Fällen hast bereits die URL zum Projekt auf GitHub. Eine solche URL könnte z.B. so aussehen: <a href="https://github.com/LernMoment/ballspiel">https://github.com/LernMoment/ballspiel</a>. Diese URL benötigen wir später in Visual Studio um das passende Projekt auf deinen Rechner zuholen.</p>
<p>Solltest du die URL noch nicht haben, aber, z.B. über eine Recherche oder einen anderen Artikel, das passende Projekt auf GitHub gefunden haben, dann findest du die URL, in dem du (1) auf den grünen <em>Code</em>-Button klickst. Dort stellst du sicher, dass (2) <em>Https</em> ausgewählt ist und (3) kopierst dir dann die URL über das Symbol hinter der URL.</p>
<p><img src="https://www.lernmoment.de/images/git-projekt-klonen/github-url-kopieren.png" alt="URL zum GitHub Projekt kopieren" /></p>
<h2 id="2---das-projekt-klonen">2 - Das Projekt klonen</h2>
<p>Nun öffnest du Visual Studio und auf dem Bildschirm (mit der hilfreichen Überschrift “Visual Studio 2019”) wählst du <em>“Repository klonen”</em> aus. In dem Feld <em>“Repositoryspeicherort”</em> fügst du die in Schritt #1 kopierte URL ein. Das Feld <em>“Pfad”</em> lasse ich immer so wie es ist, aber du kannst es natürlich deinen Anforderungen anpassen.</p>
<p><img src="https://www.lernmoment.de/images/git-projekt-klonen/vs-repository-klonen.png" alt="Repository klonen" /></p>
<p>Danach öffnet sich bereits das Projekt in Visual Studio. Nun kannst du im <em>“Projektmappen-Explorer”</em> die zum Projekt gehörenden Dateien sehen und das Projekt natürlich auch kompilieren.</p>
<h2 id="3---nächste-schritte">3 - Nächste Schritte</h2>
<p>In diesem Projekt kannst du nun Änderungen vornehmen und sie auch lokal speichern bzw. in git committen. Allerdings bekommst du die Änderungen dann <strong>nicht</strong> zurück auf GitHub. Das liegt daran, dass du hier einen <em>Clone</em> und keinen <em>Fork</em> erstellt hast. Wenn du den Unterschied zwischen <em>Clone</em> und <em>Fork</em> nicht kennst, dann kann ich dir mein <a href="https://www.udemy.com/github-tutorial-deutsch/">kostenloses GitHub Tutorial</a> empfehlen.</p>
<p>Weitere Aktivitäten die du mit der “neuen” Git-Oberfläche in Visual Studio 2019 machen kannst, hat Microsoft in <a href="https://docs.microsoft.com/de-de/visualstudio/ide/git-with-visual-studio?view=vs-2019">diesem Artikel</a> beschrieben. Etwas konkreter und einsteigerfreundlicher wirst du das auch bald hier nachlesen können. Du willst über neue Artikel von mir informiert werden? Kein Problem! Meine wöchentliche LernMail unterstützt dich als Einsteiger auf dem Weg zum C# Entwickler beim Lernen und Entwickeln. Am Ende des Artikels kannst du dich anmelden.</p>
<p>Hoffentlich hat dir diese Anleitung ein wenig geholfen beim Umgang mit <em>GitHub</em> und <em>Visual Studio</em>. Über jegliche Rückmeldung zu diesem Artikel würde ich mich sehr freuen:</p>
<p><a href="mailto:jan@lernmoment?subject=Frage%20zum%20Artikel:%20GitHub%20mit%20VisualStudio2019" class="notice-button">Fragen / Kommentare >></a></p>
<p>Viel beim durchschauen der Projekte von GitHub</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/projekt-klonen-von-github/">Ein Projekt von GitHub klonen mit Visual Studio 2019 (neue Git UI)</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 10, 2021.</p>
https://www.lernmoment.de/alle/git-server-strato-hidrive2021-01-12T01:00:00+01:002021-01-12T01:00:00+01:00Raul Katoshttps://www.lernmoment.de
<blockquote>
<p>Dies ist ein Gastartikel von Raul Katos. Vielen Dank an Raul für die viele Mühe und die detailierte Anleitung!</p>
</blockquote>
<p>Mit Visual Studio 2019 ist die Integration von git in den Entwicklungsprozess ein Leichtes geworden. Mit einem einfachen Mausklick wird ein lokales git-Repository erstellt, in welches man seine Versionsstände committen kann. Auch die Anbindung an GitHub zu einem Remote-Repository ist sehr einfach, sofern man bereits über einen GitHub-Account verfügt. Doch es gibt Situationen, da möchte man nicht auf GitHub gehen, und dann stellt sich die Frage, wie man ein <strong>Remote-Repository</strong> selbst erstellen und an Visual Studio anbinden kann, so dass auch andere Benutzer darauf zugreifen können. Dieser Beitrag beschreibt eine Möglichkeit, über <strong>HiDrive</strong> (das ist die Daten-Cloud von Strato) genau das zu erreichen.</p>
<p>Auch wenn diese Anleitung sehr ausführlich ist, die Durchführung der Schritte ist in <strong>wenigen Minuten</strong> erledigt!</p>
<h3 id="inhalt">Inhalt</h3>
<ul>
<li><a href="#vorüberlegungen">Vorüberlegungen</a></li>
<li><a href="#die-ausgangssituation">Die Ausgangssituation</a></li>
<li><a href="#erstellen-des-git-remote-repositorys-in-hidrive">Erstellen des git Remote-Repositorys in HiDrive</a></li>
<li><a href="#erstellen-des-lokalen-repositorys-in-visual-studio-2019">Erstellen des lokalen Repositorys in Visual Studio 2019</a></li>
<li><a href="#pushen-in-das-git-remote-repository-in-hidrive">Pushen in das git Remote-Repository in HiDrive</a></li>
<li><a href="#clonen-des-git-remote-repositorys-in-hidrive">Clonen des git Remote-Repositorys in HiDrive</a></li>
<li><a href="#zusammenfassung">Zusammenfassung</a></li>
<li><a href="#abschließende-anmerkungen">Abschließende Anmerkungen</a></li>
</ul>
<h2 id="vorüberlegungen">Vorüberlegungen</h2>
<p>Prinzipiell kann man als einzelner Entwickler die git-Funktionalität von Visual Studio 2019 jederzeit sofort für sein Projekt aktivieren. Ab diesem Zeitpunkt ist es möglich, Änderungen an den Quelldateien zu versionieren und damit nachvollziehen zu können. Ein so erstelltes <strong>lokales Repository</strong> kann dabei auf der lokalen Festplatte liegen oder auch auf einem Netzlaufwerk. Ein <strong>Remote-Repository</strong> kann prinzipiell auf einem Netzlaufwerk liegen, so dass ein <strong>Push</strong> vom lokalen ins Remote-Repository möglich ist. Sofern mehr als ein Entwickler an einem Projekt beteiligt sind, können diese aus dem Remote-Repository ihr lokales Repository <strong>Clonen</strong>.</p>
<p>Ein <strong>Netzlaufwerk</strong> ist jedoch in der Regel und auch sinnvollerweise nicht von außerhalb des LAN (lokales Netzwerk) erreichbar. Es ist <ins>keine gute Idee</ins>, sein NAS oder seinen Server für unbekannte Dritte nach außen aufzumachen und auf Netzwerkdienste zugreifen zu lassen. Ein lokales System nach außen abzusichern ist jedoch mit erheblichem Aufwand verbunden. Wir merken recht schnell, dass wir an der Cloud nicht vorbeikommen, wenn wir den administrativen Aufwand gering halten wollen.</p>
<p>Der <strong>Vorteil von GitHub</strong> ist, dass man es weltweit erreichen kann. Die Authentifizierung (das Anmelden bei GitHub) und damit das Rechte-Management wird durch die GitHub-Plattform bewerkstelligt. Damit ist es möglich, dass die Entwickler irgendwo auf der Welt verteilt sein können und über das Internet Zugriff auf das Repository haben.</p>
<p>Nun ist GitHub “nur” ein (kommerzieller) Anbieter, auch wenn die zusätzlichen Services von GitHub weit über das bloße Bereitstellen eines Remote-Repositorys hinausgehen. Es stellt sich die Frage, ob und wie man auch ohne GitHub ein in der Cloud gespeichertes Remote-Repository nutzen kann? Die Antwort darauf soll dieser Beitrag geben.</p>
<h2 id="die-ausgangssituation">Die Ausgangssituation</h2>
<p>Aufgrund eines Angebots wurde ich wieder einmal auf das Strato Produkt <a href="https://www.strato.de/cloud-speicher/">HiDrive</a> aufmerksam gemacht<sup>1</sup>. Neben einem Cloud-Speicher von <strong>1 TByte</strong> war in dem Angebot das komplette <strong>Schnittstellenpaket</strong> enthalten, mit dem es möglich ist, nicht nur über einen Web-Client, sondern über verschiedene Protokolle<sup>2</sup> (insbesondere für git) auf die Daten zuzugreifen.</p>
<p>Prinzipiell unterstützt <strong>git</strong> die folgenden Protokolle (siehe auch hier):</p>
<ul>
<li>Lokal (also innerhalb des lokalen Netzwerks z. B. mit file://)</li>
<li>HTTP (Dumb HTTP ab Git 1.6.6 Smart HTTP bzw. HTTPS)</li>
<li><span style="background-color: yellow">Secure Shell (SSH - kein anonymer Zugriff möglich!)</span></li>
<li>Git (über Port 9418 - aber ohne Authentifizierung!)</li>
</ul>
<p>Die hier gezeigte Vorgehensweise wird über <strong>SSH</strong> implementiert. D. h. wir brauchen später für <strong>Push</strong> und <strong>Clone</strong> einen <strong>User</strong> und ein <strong>Passwort</strong> zur Authentifizierung!</p>
<p>Der <strong>User</strong> ist derjenige, mit dem man sich an HiDrive anmeldet.
Das <strong>Passwort</strong> ist dasjenige, das zu dem HiDrive User-Account gehört.</p>
<h2 id="erstellen-des-git-remote-repositorys-in-hidrive">Erstellen des git Remote-Repositorys in HiDrive</h2>
<p>Sobald man sich bei HiDrive angemeldet hat, blickt man auf seinen privaten Cloud-Speicher.</p>
<p>Hier haben wir bereits einen Ordner <strong>Repositories</strong>, in welchem wir unsere Remote-Repositorys ablegen werden.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_15h57_08.png" alt="HiDrive - Ansicht mit zuvor erzeugtem Ordner Repositories" /></p>
<p>Wir wechseln durch Klicken in den Ordner <strong>Repositories</strong>, der noch leer ist:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h00_17.png" alt="HiDrive - Ein neues Repository anlegen" /></p>
<p>Wir erstellen jetzt innerhalb HiDrive ein neues Git-Repository.</p>
<p>Über die Schaltfläche <code class="language-plaintext highlighter-rouge">... mehr</code> öffnen wir das Funktionsmenü (1)</p>
<p>Dort wählen wir den Eintrag <code class="language-plaintext highlighter-rouge">Git-Repository erstellen</code> (2)</p>
<p><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h03_52.png" alt="HiDrive - Git-Repositoriy erstellen" /></p>
<p>Wir geben hier als Name des Repositorys <strong>MyRepository</strong> ein (1) und klicken auf die Schaltfläche <code class="language-plaintext highlighter-rouge">Erstellen</code> (2):</p>
<p><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h06_04.png" alt="HiDrive - Link zum erzeugten Repository" /></p>
<p>Zur Bestätigung wird uns ein Dialog angezeigt, in welchem der Pfad zu unserem Repository eingetragen ist
(hier: /users/[userName]/Repositories/MyRepository.git)</p>
<p>Der <strong>userName</strong> (hier rot anonymisiert) entspricht dem User, mit dem wir uns bei HiDrive angemeldet haben.</p>
<p>Den Pfad <code class="language-plaintext highlighter-rouge">Kopieren</code> wir uns in die Zwischenablage (1) und klicken anschließend auf <code class="language-plaintext highlighter-rouge">OK</code> (2), um den Dialog zu schließen.</p>
<p>Nun sehen wir im Ordner <strong>Repositories</strong> das eben erzeugt Repository <strong>MyRepository</strong>:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h09_24.png" alt="HiDrive - das neue MyRepository.git" /></p>
<p>Wir wechseln nun in das Repository <strong>MyRepository.git</strong> (1):</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h12_00.png" alt="HiDrive - Inhalt von MyRepository.git" /></p>
<p>Wir sehen die typischen Verzeichnisse und Dateien eines git-Repositorys.</p>
<p>Damit sind wir innerhalb von HiDrive fertig.</p>
<h2 id="erstellen-des-lokalen-repositorys-in-visual-studio-2019">Erstellen des lokalen Repositorys in Visual Studio 2019</h2>
<blockquote>
<p>Anmerkung: prinzipiell kann die Anlage des lokalen Repositorys, sowie die Angabe des Remote-Repositorys in einem Schritt erledigt werden. Es ist aber auch möglich, ein Repository zunächst lokal zu erstellen, und es später in ein Remote-Repository zu pushen. Hier gehen wir aus didaktischen Gründen den etwas umständlicheren Weg: erst lokal initialisieren und später pushen.</p>
</blockquote>
<p>Für diese Anleitung erstelle ich ein Test-Projekt mit dem Namen <strong>TestProjekt</strong> als C# WPF-Anwendung:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_16h58_19.png" alt="VS2019 - Neues Projekt konfigurieren" /></p>
<p>Wir geben also einen <code class="language-plaintext highlighter-rouge">Projektnamen</code> ein (1), wählen den <code class="language-plaintext highlighter-rouge">Ort</code>, wo wir unsere Repositorys ablegen (2) und klicken auf <code class="language-plaintext highlighter-rouge">Erstellen</code> (3).</p>
<p>Wir schauen uns das Ergebnis im Windows Explorer an:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h02_52.png" alt="Explorer - Die neue Projektmappe" /></p>
<p>Zur Verdeutlichung habe ich die unsichtbaren Elemente im <strong>Windows Explorer</strong> sichtbar geschaltet.</p>
<p>Hier sehen wir das <em>.vs</em> Verzeichnis, das Visual Studio angelegt hat (1).</p>
<p>Sobald das Projekt in Visual Studio 2019 erzeugt wurde, findet sich unten rechts im Visual Studio 2019 Fenster der Hinweis auf die Quellcodeverwaltung:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h00_14.png" alt="VS2019 - Zur Quellcodeverwaltung hinzufügen" /></p>
<p>Hier klickt man zuerst auf <code class="language-plaintext highlighter-rouge">Zur Quellcodeverwaltung hinzufügen</code> (1)</p>
<p>Anschließend sollte <code class="language-plaintext highlighter-rouge">Git</code> angeboten werden, worauf wir dann klicken (2):</p>
<p>Jetzt öffnet sich der Dialog <strong>GIT-Repository erstellen</strong>:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h03_56.png" alt="VS2019 - GIT-Repository erstellen" /></p>
<p>Da wir zuerst nur ein lokales git-Repository initialisieren, wählen wir <code class="language-plaintext highlighter-rouge">Nur lokal</code> aus (1).</p>
<p>Als <code class="language-plaintext highlighter-rouge">Lokaler Pfad</code> wird der Ordner vorgeschlagen, den wir als Projektmappe zuvor angelegt haben (2).</p>
<p>Zum Initialisieren des lokalen git-Repositorys klicken wir abschließend auf die Schaltfläche <code class="language-plaintext highlighter-rouge">Erstellen</code> (3).</p>
<p>Schauen wir uns das Ergebnis abermals im <strong>Windows Explorer</strong> an:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h24_37.png" alt="Explorer - Lokales Git-Repository und git-Files" /></p>
<p>Im Ordner unserer Projektmappe ist nun ein weiteres unsichtbares Verzeichnis - unser lokales git-Repository - <strong>.git</strong> (1) entstanden.</p>
<p>Außerdem liegen in der Projektmappe zwei weitere Dateien (<strong>.gitattributes</strong> und <strong>.gitignore</strong>) (2)</p>
<p>Ab jetzt können wir jede Änderung in unser lokales git-Repository committen.</p>
<p>Im folgenden Abschnitt werden wir nun eine Verbindung zu unserem Remote-Repository, das wir in HiDrive eingerichtet haben, herstellen.</p>
<h2 id="pushen-in-das-git-remote-repository-in-hidrive">Pushen in das git Remote-Repository in HiDrive</h2>
<p>Innerhalb von Visual Studio 2019 gibt es standardmäßig auf der rechten Seite neben dem Projektmappen Explorer einen zweiten Reiter mit der Beschriftung <strong>Git-Änderungen: TestProjekt:</strong></p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h38_01.png" alt="VS2019 - Git-Änderungen: TestProjekt" /></p>
<p>Wir aktivieren den Reiter <code class="language-plaintext highlighter-rouge">Git-Änderungen: TestProjekt</code> (1) und geben ggf. in das Textfeld <code class="language-plaintext highlighter-rouge">Nachricht eingeben</code> (2) einen sinnvollen Kommentar ein, z. B. “Initiale Anlage des Projekts”. Anschließend klicken wir auf die Schaltfläche <code class="language-plaintext highlighter-rouge">Push</code> (3).</p>
<blockquote>
<p>Da wir das Projekt bereits in ein lokal initialisiertes Repository commited haben, steht hier, dass es keine ungestageten (sic!) Änderungen gäbe. Sollten zwischenzeitlich Änderungen gemacht worden sein, würden diese hier aufgeführt. Ein Kommentar im Textfeld Nachricht eingeben sollte dann obligatorisch sein.</p>
</blockquote>
<p>Es öffnet sich nun wieder der Dialog <strong>GIT-Repository erstellen</strong>:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_17h55_00.png" alt="VS2019 - GIT-Repository erstellen" /></p>
<p>Hier wählen wir jetzt <code class="language-plaintext highlighter-rouge">Vorhandenes Remoterepository</code> (1)</p>
<p>Als <code class="language-plaintext highlighter-rouge">Remote-URL</code> geben wir jetzt den zuvor in HiDrive kopierten Pfad zum Remote-Repository mit Präfix ein</p>
<p>Anstelle von [userName] tragen wir unseren Anmeldenamen für HiDrive ein (2):</p>
<p>[userName]@git.hidrive.strato.com:/users/[userName]/Repositories/MyRepository.git</p>
<p>Abschließend klicken wir auf <code class="language-plaintext highlighter-rouge">Push</code> (3)</p>
<p>Nun folgt der Dialog <strong>Enter Password</strong>:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_18h23_50.png" alt="VS2019 - Enter Password für Push" /></p>
<p>Hier müssen wir noch das <strong>Passwort</strong> für den Zugriff auf HiDrive eingeben (1) und mittels <code class="language-plaintext highlighter-rouge">OK</code> (2) bestätigen:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_18h28_42.png" alt="VS2019 - 'master' wurde erfolgreich nach 'origin' gepusht" /></p>
<p>Wenn alles geklappt hat, sehen wir rechts im Reiter <code class="language-plaintext highlighter-rouge">Git-Änderungen: TestProjekt</code> die entsprechende Erfolgsmeldung (1).</p>
<h2 id="clonen-des-git-remote-repositorys-in-hidrive">Clonen des git Remote-Repositorys in HiDrive</h2>
<p>Um nun den Kreis zu schließen, soll hier noch kurz dargestellt werden, wie man das Remote-Repository klont. Zu diesem Zweck klone ich in ein anderes Verzeichnis das Projekt, das ich eben gepusht hatte.</p>
<p>Hierzu starten wir Visual Studio neu:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_21h52_48.png" alt="VS2019 - Los geht's: Repository klonen" /></p>
<p>Jetzt wählen wir <code class="language-plaintext highlighter-rouge">Repository klonen</code> (1)</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_21h54_33.png" alt="VS2019 - Repository klonen" /></p>
<p>Beim <code class="language-plaintext highlighter-rouge">Repositoryspeicherort</code> geben wir den Pfad ein, den wir vom Pushen bereits kennen.</p>
<p>Anstelle von [userName] tragen wir unseren Anmeldenamen für HiDrive ein (1):</p>
<p>[userName]@git.hidrive.strato.com:/users/[userName]/Repositories/MyRepository.git</p>
<p>Für diesen Test lassen wir von Visual Studio ein neues Verzeichnis (<strong>ProjektTest</strong>) als Projektmappe anlegen (2)</p>
<p>Abschließend starten wir durch Klicken auf die Schaltfläche <code class="language-plaintext highlighter-rouge">Klonen</code> den Abruf der Dateien (3)</p>
<p>Wir müssen uns wieder bei HiDrive anmelden, es folgt also der Dialog <strong>Enter Password</strong>:</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_18h23_50.png" alt="VS2019 - Enter Password für Clone" /></p>
<p>Wir geben das <strong>Passwort</strong> für den Zugriff auf HiDrive ein (1) und bestätigen mittels <code class="language-plaintext highlighter-rouge">OK</code> (2)</p>
<p>Das Projekt ist nun in Visual Studio 2019 verfügbar.</p>
<p>Das Ergebnis sehen wir uns noch im <strong>Windows Explorer</strong> an:</p>
<p><img src="https://www.lernmoment.de/images/git-server-hidrive/2021-01-02_22h11_03.png" alt="Explorer - Projektmappe 'ProjektTest'" /></p>
<p>Wir sehen, dass ein neues Verzeichnis <strong>ProjektTest</strong> als Projektmappe angelegt wurde (1)</p>
<p>Zu beachten ist, dass das Projekt selbst noch den ursprünglichen Namen <strong>TestProjekt</strong> hat, was so in Ordnung ist.</p>
<h2 id="zusammenfassung">Zusammenfassung</h2>
<ul>
<li>Diese Anleitung hat gezeigt, dass es möglich ist, die Quellcodeverwaltung mittels eines Git-Repositorys, das innerhalb von HiDrive erstellt werden kann, an Visual Studio 2019 anzudocken.</li>
<li>Damit ist es möglich, mittels Visual Studio 2019 einen Versionsstand mit Push ins Remote-Repository zu übertragen bzw. mittels Clone ein lokales Repository aus dem Remote-Repository zu erzeugen.</li>
<li>In HiDrive können weitere User kostenpflichtig hinzugebucht werden. Jeder eingerichtete HiDrive-User hat dann auf <ins>alle Repositorys im \public Ordner</ins> Zugriff. Eine dezidierte Freigabe für bestimmte User auf einzelne Repositorys im \public Ordner ist jedoch nicht möglich!</li>
<li>Die Standardmechanismen der beschriebenen Vorgehensweise erlauben eine Authentifizierung mittels SSH, was jedoch die manuelle Eingabe eines Passworts bei Push und Clone erforderlich macht.</li>
<li>Der beschriebene Weg erlaubt jedoch aufgrund SSH keinen anonymen Zugriff, was im Wesen von SSH begründet liegt. Ein Ausweg könnte ein SSH-Schlüssel sein (s. u.).</li>
</ul>
<h2 id="abschließende-anmerkungen">Abschließende Anmerkungen</h2>
<ul>
<li><strong>Weitere Benutzer für HiDrive</strong>: Leider kann der Zugriff auf bestimmte Repositorys im \public-Ordner nicht für bestimmte HiDrive-User beschränkt werden. D. h. entweder ist das Repository in \public und dann für alle gebuchten HiDrive-User sichtbar, oder es befindet sich im eigenen Bereich und ist ausschließlich für diesen User sichtbar. Dazwischen gibt es leider nichts.</li>
<li><strong>Verhindern der Passwort-Eingabe</strong>: Um zu vermeiden, dass man jeweils bei Push bzw. Clone das Passwort eingeben muss, kann man ggf. einen SSH-Schlüssel generieren. HiDrive erlaubt es, den SSH-Schlüssel zu hinterlegen. Wie dieser erzeugt und mittels Visual Studio 2019 genutzt werden kann, werde ich ggf. in einem weiteren Beitrag erläutern.</li>
<li><strong>Public Zugriff auf ein Remote-Repository</strong>: ein rein anonymer Zugriff auf ein git-Repository in HiDrive kann bis dato nicht bewerkstelligt werden. Zwar lassen sich im HiDrive Ordner als HTTPS-URL freigeben, diese kann man aber nicht in der Quellcodeverwaltung in Visual Studio 2019 hinterlegen, d. h. so funktioniert es nicht.</li>
</ul>
<hr />
<p><sup>1</sup> Es lohnt sich manchmal, bei Strato auf ein Angebot zu warten. In meinem Fall zahlte ich 1 € für die Einrichtung, in den ersten 12 Monaten 0 € und anschließend ab dem 13. Monat 7 €/Monat.</p>
<p><sup>2</sup> Folgende Protokolle werden mit dem HiDrive Schnittstellenpaket unterstützt:</p>
<ul>
<li>FTP (ohne Verschlüsselung - File Transfer Protocol - sehr alt)</li>
<li>FTPS (File Transfer Protocol verschlüsselt per TLS)</li>
<li>SFTP (File Transfer Protocol SSH verschlüsselt)</li>
<li>WebDAV (wahlweise verschlüsselt oder unverschlüsselt - mobiler Zugriff auf HiDrive z. B. für CalDAV)</li>
<li>SMB / CIFS (ab SMB v3 wahlweise verschlüsselt oder unverschlüsselt - HiDrive als Netzlaufwerk in Windows nutzbar)</li>
<li>rsync (wahlweise verschlüsselt oder unverschlüsselt - Synchronisation über das Internet mit NAS / Netzwerkfestplatte)</li>
<li>SCP (verschlüsselte Datenübertragung über ein Rechnernetz)</li>
<li>git (Lokal, SSH, HTTP, Git - s. u.)</li>
</ul>
<p><a href="https://www.lernmoment.de/alle/git-server-strato-hidrive/">Git-Server auf Strato HiDrive aufsetzen und verwenden</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am January 12, 2021.</p>
https://www.lernmoment.de/alle/wpf-controls-deaktivieren-verstecken2020-04-18T10:00:09+02:002020-04-18T10:00:09+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Im <a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/">WPF-Übungskurs für Einsteiger</a> ist eine Aufgabe einen Hinweis in einem <code class="language-plaintext highlighter-rouge">Label</code> anzuzeigen. Grundsätzlich ist das erstmal keine Herausforderung, weil die einzige Aufgabe die ein <code class="language-plaintext highlighter-rouge">Label</code> hat, ist einen Text anzuzeigen 😁. Da das <code class="language-plaintext highlighter-rouge">Label</code> in diesem Fall jedoch über anderen Steuerelementen liegt, soll es ausgeblendet werden, solange kein Hinweis angezeigt wird.</p>
<p>Doch wie kann ein <code class="language-plaintext highlighter-rouge">Label</code> oder auch jedes anderen Steuerelement eigentlich ausgeblendet werden? Wenn du die Suchmaschine deines Vertrauens fragst, kommst du ziemlich schnell auf eine von 2 Eigenschaften:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">IsEnabled</code> - Gibt an ob ein Steuerelement aktiv ist</li>
<li><code class="language-plaintext highlighter-rouge">Visibility</code> - Gibt an ob ein Steuerelement sichtbar ist</li>
</ul>
<p>Dabei ist es wichtig zu verstehen, dass Aktivierung und Sichtbarkeit zwei unterschiedliche Dinge sind.</p>
<h3 id="steuerelemente-deaktivieren-isenabled">Steuerelemente deaktivieren <code class="language-plaintext highlighter-rouge">IsEnabled</code></h3>
<p>Wenn du ein Steuerelement über <code class="language-plaintext highlighter-rouge">IsEnabled = false</code> deaktivierst, dann ist es immer noch sichtbar. Ein deaktiviertes Steuerelement ist allerdings nicht bedienbar. Um dem Benutzer zu zeigen, dass es nicht verwendet werden kann, ist ein deaktiviertes Steuerelement gräulich dargestellt.</p>
<p>Das hast du vielleicht schon mal bei einem <code class="language-plaintext highlighter-rouge">Button</code> zum speichern oder so gesehen. Solange es keine Änderungen gibt diee gespeichert werden können, kannst du einen solchen <code class="language-plaintext highlighter-rouge">Button</code> deaktivieren. Das signalisiert dem Benutzer, dass die Aktion momentan nicht verfügbar ist. Als Entwickler hilft es dir, dass du dir sicher sein kannst, dass eine Aktion nur dann ausgeführt wird, wenn sie auch tatsächlich sinnvolle Resultate liefern kann.</p>
<p>In folgendem Bild siehst du ein paar Steuerelemente und wie sie aussehen wenn sie aktiv bzw. nicht aktiv sind:</p>
<p><img src="https://www.lernmoment.de/images/wpf-controls-deaktivieren/isenabled-example.jpg" alt="Aussehen von Steuerelementen die aktiv bzw. nicht aktiv sind" /></p>
<h3 id="steuerelemente-verstecken-visibility">Steuerelemente verstecken <code class="language-plaintext highlighter-rouge">Visibility</code></h3>
<p>Die Sichbarkeit eines Steuerelements wird durch die Eigenschaft <code class="language-plaintext highlighter-rouge">Visibility</code> beeeinflußt. Dabei gibt es die folgenden möglichen Werte für diese Eigenschaft:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Visible</code> - Das Steuerelement ist sichtbar</li>
<li><code class="language-plaintext highlighter-rouge">Hidden</code> - Das Steuerelement ist nicht sichtbar, aber es wird im Layout berücksichtigt, als wäre es sichtbar. Es entsteht also eine Lücke auf der Oberfläche wo ansonsten das Steuerelement angezeigt würde.</li>
<li><code class="language-plaintext highlighter-rouge">Collapsed</code> - Das Steuerelement ist nicht sichtbar und wird nicht im Layout berücksichtigt. Die umgebenden Steuerelement nehmen also den entstehenden Platz ein.</li>
</ul>
<p><img src="https://www.lernmoment.de/images/wpf-controls-deaktivieren/visibility-hidden.jpg" alt="Steuerelementen mit Visibility.Hidden" /></p>
<p><img src="https://www.lernmoment.de/images/wpf-controls-deaktivieren/visibility-collapsed.jpg" alt="Steuerelementen mit Visibility.Collapsed" /></p>
<p>Wichtig ist dabei, dass du nur einen Unterschied zwischen <code class="language-plaintext highlighter-rouge">Hidden</code> und <code class="language-plaintext highlighter-rouge">Collapsed</code> siehst, wenn dein Layout dieses zu lässt. In dem eingangs erwähnten Beispiel im <a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/">WPF-Übungskurs für Einsteiger</a> verwenden wir ein <code class="language-plaintext highlighter-rouge">Grid</code>. Da jedes Steuerelement in seiner eigenen Zelle ist, wirst du dort zwischen <code class="language-plaintext highlighter-rouge">Hidden</code> und <code class="language-plaintext highlighter-rouge">Collapsed</code> keinen Unterschied sehen.</p>
<p>Nachfolgend noch der <em>XAML</em>-Code den ich verwendet habe für die beiden Bilder. Darin siehst du, dass die drei <code class="language-plaintext highlighter-rouge">Button</code> nebeneinander in einem <code class="language-plaintext highlighter-rouge">StackPanel</code> liegen. Daher ergibt sich auch ein Unterschied im Layout, weil so mit <code class="language-plaintext highlighter-rouge">Collapsed</code> der Platz frei wird, dass <code class="language-plaintext highlighter-rouge">Test3-Button</code> nach links rutschen kann.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">TextElement.FontSize=</span><span class="s">"30"</span><span class="nt">></span>
<span class="nt"><Grid.RowDefinitions></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"></Grid.RowDefinitions></span>
<span class="nt"><StackPanel</span> <span class="na">Orientation=</span><span class="s">"Horizontal"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span><span class="nt">></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Test1"</span> <span class="na">Margin=</span><span class="s">"10"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Test2"</span> <span class="na">Margin=</span><span class="s">"10"</span>
<span class="na">Visibility=</span><span class="s">"{Binding ElementName=VisibilitySelector, Path=SelectedValue.Content}"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Test3"</span> <span class="na">Margin=</span><span class="s">"10"</span><span class="nt">/></span>
<span class="nt"></StackPanel></span>
<span class="nt"><ComboBox</span> <span class="na">x:Name=</span><span class="s">"VisibilitySelector"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Margin=</span><span class="s">"50"</span> <span class="na">SelectedIndex=</span><span class="s">"0"</span>
<span class="na">HorizontalAlignment=</span><span class="s">"Center"</span> <span class="na">VerticalAlignment=</span><span class="s">"Center"</span><span class="nt">></span>
<span class="nt"><ComboBox.Items></span>
<span class="nt"><ComboBoxItem</span> <span class="na">Content=</span><span class="s">"Visible"</span><span class="nt">/></span>
<span class="nt"><ComboBoxItem</span> <span class="na">Content=</span><span class="s">"Collapsed"</span><span class="nt">/></span>
<span class="nt"><ComboBoxItem</span> <span class="na">Content=</span><span class="s">"Hidden"</span><span class="nt">/></span>
<span class="nt"></ComboBox.Items></span>
<span class="nt"></ComboBox></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Möchtest du dein Wissen testen und etwas Erfahrung in der Erstellung von Windows-Oberflächen mit WPF und C# sammeln?</p>
<div class="subscribe-notice">
<h5>Dann melde dich hier zum kostenlosen WPF Übungskurs für Einsteiger an.</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Erfahre mehr >></a>
</div>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/wpf-controls-deaktivieren-verstecken/">WPF-Steuerelementen deaktivieren und verstecken</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am April 18, 2020.</p>
https://www.lernmoment.de/alle/zugriff-wpf-controls-code-behind2020-04-03T10:00:09+02:002020-04-03T10:00:09+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Ein zentraler Aspekt der Entwicklung von Oberflächen ist, dass du zur Laufzeit Daten mithilfe der Steuerelemente auf der Oberfläche visualisieren kannst. Hier ein paar übliche Szenarien und wie sie ein Steuerelement beeinflussen können:</p>
<ul>
<li>Speichern von Einstellungen nur erlauben, wenn es tatsächlich Änderungen an den Einstellungen gab - Du hast das vielleicht schon bei einigen Anwendungen gesehen. Ein <code class="language-plaintext highlighter-rouge">Button</code> (z.B. <em>Ok</em> oder <em>Speichern</em>) kann erst dann angeklickt werden, wenn du in dem Fenster auch tatsächlich Änderungen vorgenommen hast.</li>
<li>Anzeigen von Daten die während der Ausführung der Anwendung erzeugt werden - In einer Auftragsverwaltung gibt es beispielsweise die Möglichkeit einen neuen Auftrag anzulegen. Dieser wird dann als neuer Eintrag in einer tabellarischen Übersicht (z.B. in einem <code class="language-plaintext highlighter-rouge">DataGrid</code>) angezeigt, wenn er erfolgreich angelegt wurde.</li>
<li>Anzeigen des aktuellen Verbindunsstatus zu einem Gerät (z.B. einem Server, einer Kamera, …) - Um dem Anwender zu signalisieren ob eine Verbindung (z.B. zu einem benötigten Server) besteht, wird der Status beispielsweise in einem <code class="language-plaintext highlighter-rouge">Label</code> oder der <code class="language-plaintext highlighter-rouge">StatusBar</code> aktualisiert, wenn die Anwendung erkennt, dass die Verbindung hergestellt wurde oder abgebrochen ist.</li>
</ul>
<p>Um diese Szenarien in <em>WPF</em> umzusetzen, gibt es folgende Möglichkeiten:</p>
<ol>
<li>Verändern von Steuerelementen aus dem <em>code-behind</em> (eine Erklärung was <em>code-behind</em> ist findest du im Artikel <a href="/alle/xaml-code-behind/">XAML, *.g.i.cs und code-behind in WPF</a>)</li>
<li>Datenbindung</li>
</ol>
<p>Im folgenden erkläre ich dir Möglichkeit 1 genauer. Das Thema Datenbindung gibt es dann in einem separaten Artikel.</p>
<h3 id="steuerelemente-via-sender-im-eventhandler-verändern">Steuerelemente via <code class="language-plaintext highlighter-rouge">sender</code> im EventHandler verändern</h3>
<p>Eine Möglichkeit im <em>C#</em> Quellcode auf ein Steuerelement zu zugreifen, bietet dir jeder mit dem Steuerelement verbundene <em>EventHandler</em>. Das möchte ich dir anhand eines Beispiels zeigen. Nehmen wir dazu die Definition eines <code class="language-plaintext highlighter-rouge">Button</code> in einem <code class="language-plaintext highlighter-rouge">MainWindow.xaml</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Window</span> <span class="na">x:Class=</span><span class="s">"AnwendungWPF.MainWindow"</span>
<span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span>
<span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml"</span>
<span class="na">xmlns:d=</span><span class="s">"http://schemas.microsoft.com/expression/blend/2008"</span>
<span class="na">xmlns:mc=</span><span class="s">"http://schemas.openxmlformats.org/markup-compatibility/2006"</span>
<span class="na">xmlns:local=</span><span class="s">"clr-namespace:AnwendungWPF"</span>
<span class="na">mc:Ignorable=</span><span class="s">"d"</span>
<span class="na">Title=</span><span class="s">"MainWindow"</span> <span class="na">Height=</span><span class="s">"500"</span> <span class="na">Width=</span><span class="s">"500"</span><span class="nt">></span>
<span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einContainer"</span><span class="nt">></span>
<span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"einTollerButton"</span> <span class="na">Click=</span><span class="s">"EinTollerButton_Click"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
<span class="nt"></Window></span>
</code></pre></div></div>
<p>Dazu erzeugt dir <em>Visual Studio</em> automatisch (wenn du möchtest) einen <em>EventHandler</em> im <em>code-behind</em>:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">AnwendungWPF</span>
<span class="p">{</span>
<span class="c1">/// <summary></span>
<span class="c1">/// Interaction logic for MainWindow.xaml</span>
<span class="c1">/// </summary></span>
<span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">MainWindow</span> <span class="p">:</span> <span class="n">Window</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">MainWindow</span><span class="p">()</span>
<span class="p">{</span>
<span class="nf">InitializeComponent</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">EinTollerButton_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Darin wird als erster Parameter der <code class="language-plaintext highlighter-rouge">sender</code> übergeben. Dieses ist bei allen <em>Events</em> von <em>WPF</em>-Elementen gleich. D.h. innerhalb des <em>EventHandlers</em> hast du immer Zugriff auf das Steuerelement welches den <em>EventHandler</em> zur Laufzeit aufruft. Da während der Entwicklung (damit meine ich bevor kompiliert und ausgeführt wird) noch nicht klar ist, welches konkrete Steuerelement (also insbesondere welcher Datentypen) der Aufrufer ist, hat der Parameter <code class="language-plaintext highlighter-rouge">sender</code> den Datenytyp <code class="language-plaintext highlighter-rouge">object</code>.</p>
<p>Möchtest du an dem aufrufendem Steuerelement etwas ändern, musst du wissen von welchem Datentyp es ist und dann kannst du den <code class="language-plaintext highlighter-rouge">sender</code> in diesen Datentyp umwandeln (im Artikel <a href="/csharp-tutorial-deutsch/typkonvertierung-mit-cast/">Was macht ein Cast (Typkonvertierung / Umwandlung) in C#?</a> erkläre ich dir was das bedeutet). Da in unserem Beispiel nur der eine <code class="language-plaintext highlighter-rouge">Button</code> mit dem <em>EventHandler</em> <code class="language-plaintext highlighter-rouge">EinTollerButton_Click</code> verbunden ist, ist klar, dass es sich bei dem <code class="language-plaintext highlighter-rouge">sender</code> um einen <code class="language-plaintext highlighter-rouge">Button</code> handeln muss. Somit kannst du also den <code class="language-plaintext highlighter-rouge">sender</code> per <em>Cast</em> in einen <code class="language-plaintext highlighter-rouge">Button</code> umwandeln und dann kannst du auf seine Eigenschaften zugreifen.</p>
<p>Möchtest du beispielsweise den <code class="language-plaintext highlighter-rouge">Button</code> deaktivieren nachdem er geklickt wurde, dann würde dein <em>EventHandler</em> so aussehen:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">void</span> <span class="nf">EinTollerButton_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Button</span> <span class="n">derSenderAlsButton</span> <span class="p">=</span> <span class="p">(</span><span class="n">Button</span><span class="p">)</span><span class="n">sender</span><span class="p">;</span> <span class="c1">// Cast auf Button -> gibt InvalidCastException, wenn sender kein Button ist!</span>
<span class="n">derSenderAlsButton</span><span class="p">.</span><span class="n">IsEnabled</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span> <span class="c1">// ab jetzt wird der Button grau dargestellt und kann nicht mehr geklickt werden.</span>
<span class="c1">// hier folgt weiterer Quellcode den du bei einem Click ausführen möchtest</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wie im Kommentar geschrieben, musst du jedoch aufpassen, dass der <code class="language-plaintext highlighter-rouge">sender</code> wirklich ein <code class="language-plaintext highlighter-rouge">Button</code> ist. Ist er kein <code class="language-plaintext highlighter-rouge">Button</code> bekommst du an der Stelle eine <code class="language-plaintext highlighter-rouge">InvalidCastException</code> geschmissen. Weitere Details findest du wie gesagt im Artikel <a href="/csharp-tutorial-deutsch/typkonvertierung-mit-cast/">Was macht ein Cast (Typkonvertierung / Umwandlung) in C#?</a>.</p>
<h3 id="steuerelement-über-das-umgebende-window-verändern">Steuerelement über das umgebende <code class="language-plaintext highlighter-rouge">Window</code> verändern</h3>
<p>Nun hat nicht jedes Steuerelement einen <em>EventHandler</em> und du möchtest vielleicht auch an einem Steuerelement etwas verändern, wenn nicht gerade ein <code class="language-plaintext highlighter-rouge">Event</code> ausgelöst wurde. Dann kannst du im <em>code-behind</em> direkt auf das Steuerelement über seinen Namen zugreifen. Warum die Steuerelemente im <em>code-behind</em> verfügbar sind, erkläre ich dir im Artikel <a href="/alle/xaml-code-behind/">XAML, *.g.i.cs und code-behind in WPF</a>.</p>
<p>Kommen wir auf das Beispiel von eben zurück. Wenn du dir nochmals das <em>XAML</em> anschaust, siehst du, dass ich dort einen <code class="language-plaintext highlighter-rouge">Button</code> mit dem Namen <code class="language-plaintext highlighter-rouge">einTollerButton</code> angelegt habe. Nachdem die <code class="language-plaintext highlighter-rouge">InitializeComponent</code> Methode im <em>Konstruktor</em> vom <code class="language-plaintext highlighter-rouge">MainWindow</code> aufgerufen wurde, kannst du über den Namen auf das Steuerelement zugreifen:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">MainWindow</span> <span class="p">:</span> <span class="n">Window</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">MainWindow</span><span class="p">()</span>
<span class="p">{</span>
<span class="nf">InitializeComponent</span><span class="p">();</span>
<span class="n">einTollerButton</span><span class="p">.</span><span class="n">Content</span> <span class="p">=</span> <span class="s">"Text auf Button!"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">EineBeliebigeMethode</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// auch hier kann auf den Button zugegriffen werden, weil wir im Kontext des MainWindow sind.</span>
<span class="n">einTollerButton</span><span class="p">.</span><span class="n">IsEnabled</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>Wichtig:</strong> Durch die <code class="language-plaintext highlighter-rouge">InitializeComponent</code> Methode werden erst die ganzen Steuerelemente angelegt. Versuchst du vor dem Aufruf der Methode auf ein Steuerelement zu zugreifen, oder entfernst du den Aufruf dieser Methode, gibt es zur Laufzeit eine <code class="language-plaintext highlighter-rouge">NullReferenceException</code>!!!</p>
<h3 id="zugriff-auf-steuerelemente-über-den-umgebenden-container">Zugriff auf Steuerelemente über den umgebenden Container</h3>
<p>In jedem <em>XAML Root Element</em> muss mindestens ein <em>Container</em> definiert sein. Ein solcher <em>Container</em> ist beispielsweise das <code class="language-plaintext highlighter-rouge">Grid</code>-Panel (Mehr dazu im Artikel <a href="/alle/wpf-grid-panel-xaml-grundlagen/">Grundlagen des WPF Grid-Panels in XAML</a>).</p>
<p>Steuerelemente werden nur angezeigt, wenn sie in einem <em>Container</em> enthalten sind. In <em>XAML</em> kannst du sogar ein <em>Steuerelement</em> nur innerhalb eines <em>Container</em> anlegen. Ansonsten beschwert sich der <em>Compiler</em>.</p>
<p>Jeder <em>Container</em> hat die Eigenschaft <code class="language-plaintext highlighter-rouge">Children</code> vom Typ <code class="language-plaintext highlighter-rouge">UIElementCollection</code>. Darin sind alle Steuerelemente enthalten, die im Kontext des <em>Container</em> definiert sind. Somit kannst du über die Eigenschaft <code class="language-plaintext highlighter-rouge">Children</code> auf die Steuerelemente zugreifen.</p>
<p>Um das am Beispiel zu zeigen, lege ich erstmal ein paar weitere Steuerelemente im <em>XAML</em> an (ich zeige jetzt nur noch das <code class="language-plaintext highlighter-rouge">Grid</code>, der Rest bleibt wie vorher):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einContainer"</span><span class="nt">></span>
<span class="nt"><Label</span> <span class="na">x:Name=</span><span class="s">"einLabel"</span> <span class="na">Content=</span><span class="s">"Gib etwas ein:"</span><span class="nt">/></span>
<span class="nt"><TextBox</span> <span class="na">x:Name=</span><span class="s">"eineTextBox"</span> <span class="na">ToolTip=</span><span class="s">"Gib einen Text ein!"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"okButton"</span> <span class="na">Content=</span><span class="s">"Ok"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"speichernButton"</span> <span class="na">Content=</span><span class="s">"Speichern"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Möchtest du nun beispielsweise alle Steuerelemente vom Typ <code class="language-plaintext highlighter-rouge">Button</code> deaktivieren (z.B. um erst eine Aktion auszuführen, wenn in der <code class="language-plaintext highlighter-rouge">TextBox</code> etwas eingegeben wurde), dann könntest du das so machen:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">foreach</span> <span class="p">(</span><span class="n">UIElement</span> <span class="n">item</span> <span class="k">in</span> <span class="n">einContainer</span><span class="p">.</span><span class="n">Children</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">item</span> <span class="k">is</span> <span class="n">Button</span> <span class="n">derButton</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">derButton</span><span class="p">.</span><span class="n">IsEnabled</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Da die Eigenschaft <code class="language-plaintext highlighter-rouge">Children</code> vom Typ <code class="language-plaintext highlighter-rouge">UIElementCollection</code> ist, kannst du mithilfe der <code class="language-plaintext highlighter-rouge">foreach</code>-Schleife über alle enthaltenen Steuerelemente laufen. Um nun auf die jeweiligen Details der <code class="language-plaintext highlighter-rouge">UIElement</code> zugreifen zu können, teste ich mithilfe von <code class="language-plaintext highlighter-rouge">item is Button derButton</code> ob <code class="language-plaintext highlighter-rouge">item</code> vielleicht ein <code class="language-plaintext highlighter-rouge">Button</code> ist und wenn ja, dann deaktiviere ich ihn.</p>
<p>Wie du anhand des Beispiels siehst, ist diese Art des Zugriffs hauptsächlich dafür geeignet, alle Steuerelemente eines gewissen Typs zu manipulieren. Ansonsten ist der Zugriff über den <em>Namen</em> (wie im letzten Abschnitt beschrieben) wesentlich einfacher.</p>
<p>Nun kennst du die 3 wichtigsten Arten um auf die Steuerelemente im <em>code-behind</em> zu zugreifen. Das hier gewonnene theoretische Wissen kannst du im <em>WPF</em>-Übungskurs direkt in die Praxis umsetzen:</p>
<div class="subscribe-notice">
<h5>Melde dich jetzt (unverbindlich und kostenlos) für den WPF Übungskurs an:</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Los gehts >></a>
</div>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/zugriff-wpf-controls-code-behind/">Eigenschaften von WPF-Steuerelementen im Quellcode setzen</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am April 03, 2020.</p>
https://www.lernmoment.de/alle/hinweise-anzeigen-mit-messagebox2020-04-03T10:00:09+02:002020-04-03T10:00:09+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Es gibt verschiedene Szenarien in denen es hilfreich ist dem Benutzer einer <em>WPF</em>-Anwendung einen Hinweis anzuzeigen. Hier ein paar Möglichkeiten:</p>
<ul>
<li>Der Benutzer macht eine ungültige Eingabe</li>
<li>Der Benutzer möchte eine Funktionalität ausführen die momentan nicht verfügbar ist (z.B. weil die Verbindung zu einem Server fehlt)</li>
<li>Der Benutzer muss eine Eingabe bestätigen (z.B. das Löschen eines Datensatzes)</li>
<li>Die Anwendung braucht zusätzliche Informationen um weiter machen zu können</li>
</ul>
<p>Die einfachste Möglichkeit um solche Interaktionen mit dem Benutzer in <em>WPF</em> abzubilden ist die <code class="language-plaintext highlighter-rouge">MessageBox</code>:</p>
<p><img src="https://www.lernmoment.de/images/hinweise-anzeigen-mit-messagebox/messagebox-fehler-ok.jpg" alt="Anzeigen eines Fehlers mit einer MessageBox" /></p>
<p><strong>WICHTIG:</strong> Auch wenn die <code class="language-plaintext highlighter-rouge">MessageBox</code> einfach zu vewenden ist, ist sie häufig nicht die passende Wahl. Für die meisten Szenarien gibt es in WPF bessere Mittel, weil die <code class="language-plaintext highlighter-rouge">MessageBox</code> nicht das optimale <em>Bedienerlebnis (User Experience oder UX auf Englisch)</em> bietet. So ist es beispielsweise sinnvoller direkt an einer <code class="language-plaintext highlighter-rouge">TextBox</code> einen Eingabefehler kenntlich zu machen als einen Dialog anzuzeigen der nochmals vom Benutzer bestätigt werden muss. Trotzdem wirst du gerade beim Einstieg in <em>WPF</em> häufig die <code class="language-plaintext highlighter-rouge">MessageBox</code> verwenden was auch okay ist. Bessere Varianten zeige ich dir in weiteren Artikeln 😉.</p>
<h3 id="text--überschrift-in-einer-messagebox-anzeigen">Text & Überschrift in einer MessageBox anzeigen</h3>
<p>Die Klasse <code class="language-plaintext highlighter-rouge">MessageBox</code> bietet lediglich eine statische Methode mit unterschiedlichen Parametern an. Mithilfe von <code class="language-plaintext highlighter-rouge">MessageBox.Show("")</code> kannst du einen modalen Dialog anzeigen. In dieser einfachsten Form hat der Dialog keine Überschrift, kein zusätzliches Icon und lediglich einen <code class="language-plaintext highlighter-rouge">Button</code> (<em>Ok</em>):</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MessageBox</span><span class="p">.</span><span class="nf">Show</span><span class="p">(</span><span class="s">"Dieses Kästchen ist bereits belegt! Wähle ein anderes."</span><span class="p">);</span>
</code></pre></div></div>
<p>Wahrend der Ausführung bekommst du damit diesen Dialog angezeigt:</p>
<p><img src="https://www.lernmoment.de/images/hinweise-anzeigen-mit-messagebox/messagebox-default.jpg" alt="Einfachste Form einer MessageBox" /></p>
<p>Da es sich bei der <code class="language-plaintext highlighter-rouge">Show</code>-Methode um einen synchronen Aufruf handelt, wird deine Anwendung solange blockiert, bis der Anwender den Dialog wieder schließt. Verwendest du also <code class="language-plaintext highlighter-rouge">MessageBox.Show</code> an einer Stelle in deinem Quellcode, wird die nächste Zeile im Quellcode erst dann ausgeführt, wenn der Benutzer einen <code class="language-plaintext highlighter-rouge">Button</code> oder das <code class="language-plaintext highlighter-rouge">X</code> geklickt hat.</p>
<p>Der nächste Parameter in <code class="language-plaintext highlighter-rouge">MessageBox.Show()</code> ist dann die Überschrift:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MessageBox</span><span class="p">.</span><span class="nf">Show</span><span class="p">(</span><span class="s">"Dieses Kästchen ist bereits belegt! Wähle ein anderes."</span><span class="p">,</span> <span class="s">"Unzulässiger Zug"</span><span class="p">);</span>
</code></pre></div></div>
<p>Damit wird in der Titelzeile des Dialogs die Überschrift “Unzulässiger Zug” angezeigt (siehe Bild am Anfang des Artikels).</p>
<h3 id="fragen-stellen-mit-der-messagebox">Fragen stellen mit der MessageBox</h3>
<p>Über einen weiteren Parameter in der <code class="language-plaintext highlighter-rouge">Show</code> Methode kannst du beeinflussen welche <code class="language-plaintext highlighter-rouge">Button</code> im Dialog angezeigt werden. Der Parameter hat den Typ <code class="language-plaintext highlighter-rouge">MessageBoxButton</code> welches ein <code class="language-plaintext highlighter-rouge">enum</code> mit den folgenden Werte ist:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">OK</code></li>
<li><code class="language-plaintext highlighter-rouge">OKCancel</code></li>
<li><code class="language-plaintext highlighter-rouge">YesNoCancel</code></li>
<li><code class="language-plaintext highlighter-rouge">YesNo</code></li>
</ul>
<p>Damit hast du eine gute Möglichkeit deinem Benutzer Fragen wie beispielsweise “Möchtest du die Änderungen wirklich verwerfen?” zustellen.</p>
<p>Nun reicht es natürlich nicht nur die <code class="language-plaintext highlighter-rouge">Button</code> anzuzeigen, sondern du möchtest bestimmt auch wissen welchen Button der Benutzer geklickt hat. Dazu gibt die <code class="language-plaintext highlighter-rouge">Show</code> Methode einen Wert vom Typ <code class="language-plaintext highlighter-rouge">MessageBoxResult</code> zurück. Die verschiedenen Werte und deren Bedeutung ist auf <a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.messageboxresult?view=netcore-3.1">Microsoft Docs</a> erklärt. Hier noch ein Beispiel:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MessageBoxResult</span> <span class="n">antwort</span> <span class="p">=</span> <span class="n">MessageBox</span><span class="p">.</span><span class="nf">Show</span><span class="p">(</span><span class="s">"Alle ungespeicherten Änderungen gehen verloren."</span><span class="p">,</span> <span class="s">"Anwendung wirklich schießen?"</span><span class="p">,</span> <span class="n">MessageBoxButton</span><span class="p">.</span><span class="n">OKCancel</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">antwort</span> <span class="p">==</span> <span class="n">MessageBoxResult</span><span class="p">.</span><span class="n">OK</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">System</span><span class="p">.</span><span class="n">Windows</span><span class="p">.</span><span class="n">Application</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="nf">Shutdown</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>Bitte beachte</strong>, dass die Bedeutung von <code class="language-plaintext highlighter-rouge">MessageBoxResult</code> davon abhängig ist welche <code class="language-plaintext highlighter-rouge">MessageBoxButton</code> angezeigt werden. Wird nur der <code class="language-plaintext highlighter-rouge">MessageBoxButton.OK</code> angezeigt, dann kommt <code class="language-plaintext highlighter-rouge">MessageBoxResult.OK</code> zurück egal ob der Anwender den <code class="language-plaintext highlighter-rouge">Button</code> klickt, <code class="language-plaintext highlighter-rouge">ESC</code> drückt oder den Dialog über das <code class="language-plaintext highlighter-rouge">X</code> schließt. Wird jedoch <code class="language-plaintext highlighter-rouge">MessageBoxButton.OKCancel</code> angezeigt, dann kommt für <code class="language-plaintext highlighter-rouge">X</code> und <code class="language-plaintext highlighter-rouge">ESC</code> ein <code class="language-plaintext highlighter-rouge">MessageBoxResult.Cancel</code> zurück!</p>
<h3 id="besseres-bedienerlebnis-mit-image">Besseres Bedienerlebnis mit Image</h3>
<p>Wie du am Anfang des Artikels gesehen hast, ist es auch möglich vordefinierte Bilder im Dialog anzuzeigen. Dazu gibt es die Auflistung <code class="language-plaintext highlighter-rouge">MessageBoxImage</code>. Die möglichen Werte kannst du dir auf <a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.messageboximage?view=netcore-3.1">Microsoft Docs</a> anschauen.</p>
<p>Die <code class="language-plaintext highlighter-rouge">MessageBox</code> am Anfang des Artikels wurde mit folgendem Quellcode erstellt:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MessageBox</span><span class="p">.</span><span class="nf">Show</span><span class="p">(</span><span class="s">"Dieses Kästchen ist bereits belegt! Wähle ein anderes."</span><span class="p">,</span> <span class="s">"Unzulässiger Zug"</span><span class="p">,</span> <span class="n">MessageBoxButton</span><span class="p">.</span><span class="n">OK</span><span class="p">,</span> <span class="n">MessageBoxImage</span><span class="p">.</span><span class="n">Error</span><span class="p">);</span>
</code></pre></div></div>
<p>Mit solchen Bildern im Dialog machst du es dem Benutzer etwas einfacher zu erkennen worum es sich bei deinem Hinweis genau handelt.</p>
<p>Damit solltest du die wichtigsten Funktionen von <code class="language-plaintext highlighter-rouge">MessageBox.Show()</code> kennen. Möchtest du sie vielleicht gleich in der Praxis ausprobieren?</p>
<div class="subscribe-notice">
<h5>Setze die MessageBox jetzt im kostenlosen WPF Übungskurs ein:</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Erfahre mehr >></a>
</div>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/hinweise-anzeigen-mit-messagebox/">Hinweise anzeigen mit WPF-MessageBox</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am April 03, 2020.</p>
https://www.lernmoment.de/alle/xaml-code-behind2020-04-02T12:00:09+02:002020-04-02T12:00:09+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Das Aussehen einer <em>WPF</em>-Anwendung definierst du überlicherweise in <em>XAML</em>. Neben (dem bevorzugten Weg) der Datenbindung, hast du auch die Möglichkeit deiner Anwendung Leben einzuflößen, in dem du <em>EventHandler</em> und weitere Logik im <em>code-behind</em> definierst. Doch was ist überhaupt <em>code-behind</em>, wie ist der Zusammenhang mit <em>XAML</em> und warum ist es möglich im <em>code-behind</em> auf die Steuerelemente zu zugreifen? Das alles erfährst du in diesem Artikel.</p>
<h3 id="xaml-und-das-code-behind">XAML und das code-behind</h3>
<p class="pull-right"><img src="https://www.lernmoment.de/images/xaml-code-behind/projektmappen-explorer.jpg" alt="Dateien im Projektmappen-Explorer" /></p>
<p>Jede <em>XAML</em>-Datei in <em>WPF</em> hat eine mit ihr verbundene <em>C#</em>-Quellcodedatei. Im gezeigten Beispiel siehst du eine <code class="language-plaintext highlighter-rouge">MainWindow.xaml</code>. Klappst du den Knoten im <em>Projektmappen-Explorer</em> auf, dann findest du dort die <code class="language-plaintext highlighter-rouge">MainWindow.xaml.cs</code>. Diese Datei wird auch <em>code-behind</em> genannt. Der Name kommt aus der Überlegung, dass es der (<em>C#</em>)-Quellcode hinter einem <code class="language-plaintext highlighter-rouge">XAML</code>-Container ist.</p>
<p>Um das etwas genauer zu verstehen, schauen wir uns die initiale <code class="language-plaintext highlighter-rouge">MainWindow.xaml</code> an:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Window</span> <span class="na">x:Class=</span><span class="s">"TicTacToeWPF.MainWindow"</span>
<span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span>
<span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml"</span>
<span class="na">xmlns:d=</span><span class="s">"http://schemas.microsoft.com/expression/blend/2008"</span>
<span class="na">xmlns:mc=</span><span class="s">"http://schemas.openxmlformats.org/markup-compatibility/2006"</span>
<span class="na">xmlns:local=</span><span class="s">"clr-namespace:TicTacToeWPF"</span>
<span class="na">mc:Ignorable=</span><span class="s">"d"</span>
<span class="na">Title=</span><span class="s">"MainWindow"</span> <span class="na">Height=</span><span class="s">"500"</span> <span class="na">Width=</span><span class="s">"500"</span><span class="nt">></span>
<span class="nt"><Grid></span>
<span class="nt"></Grid></span>
<span class="nt"></Window></span>
</code></pre></div></div>
<p>In dieser <em>XAML</em>-Datei ist das <code class="language-plaintext highlighter-rouge">Window</code> das <em>Root Element</em>. Jede <em>XAML</em>-Datei benötigt genau ein <em>Root Element</em> welches das äußerste <em>XAML</em>-Element ist. In <em>WPF</em> wird üblicherweise eines der folgenden Elemente als <em>Root</em> verwendet:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge"><Page></code> – Eine Seite mit Inhalten die in einem Browser angezeigt werden können (System.Windows.Controls.Page)</li>
<li><code class="language-plaintext highlighter-rouge"><Window></code> – Ein WPF-Fenster (System.Windows.Window)</li>
<li><code class="language-plaintext highlighter-rouge"><Application></code> – Eine WPF-Anwendung (System.Windows.Application)</li>
<li><code class="language-plaintext highlighter-rouge"><ResourceDictionary></code> – Eine Sammlung von Ressourcen (System.Windows.ResourceDictionary)</li>
<li><code class="language-plaintext highlighter-rouge"><UserControl></code> – Ein benutzerdefiniertes Steuerelement (System.Windows.Controls.UserControl)</li>
</ul>
<p>Für dieses <em>Root Element</em> ist nun in der <em>XAML</em>-Datei, mithilfe des <code class="language-plaintext highlighter-rouge">x:Class</code> Attributs, definiert welche Klasse den zugehörigen <em>code behind</em> beinhaltet. In folgendem Quellcode siehst du, wie die Verbindung zwischen dem <em>XAML</em>-Element <code class="language-plaintext highlighter-rouge">Window</code> und der Klasse <code class="language-plaintext highlighter-rouge">MainWindow</code> in der Datei <code class="language-plaintext highlighter-rouge">MainWindow.xaml.cs</code> hergestellt wird:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">TicTacToeWPF</span>
<span class="p">{</span>
<span class="c1">/// <summary></span>
<span class="c1">/// Interaction logic for MainWindow.xaml</span>
<span class="c1">/// </summary></span>
<span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">MainWindow</span> <span class="p">:</span> <span class="n">Window</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">MainWindow</span><span class="p">()</span>
<span class="p">{</span>
<span class="nf">InitializeComponent</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wie du siehst wird die Klasse <code class="language-plaintext highlighter-rouge">MainWindow</code> von der Klasse <code class="language-plaintext highlighter-rouge">Window</code> abgeleitet. Vereinfacht gesagt, gibt es also passend zum <code class="language-plaintext highlighter-rouge">Window</code> als <em>Root Element</em> in <em>XAML</em> die <em>C#</em>-Klasse <code class="language-plaintext highlighter-rouge">Window</code>.</p>
<h3 id="alles-ist-ein-objekt">Alles ist ein Objekt!</h3>
<p>Mit dem Aufruf der Methode <code class="language-plaintext highlighter-rouge">InitializeComponent</code> im Konstruktor von <code class="language-plaintext highlighter-rouge">MainWindow</code> kommen wir nun zum Abschluss dieses Ausflugs in die Theorie. Diese Methode zusammen mit einem <em>Code-Generator</em> ist das Bindeglied zwischen dem was du in deiner <em>XAML</em>-Datei definierst und dem was du im dazugehörigen <em>code-behind</em> verwenden kannst. Klappst du die Datei <code class="language-plaintext highlighter-rouge">MainWindow.xaml.cs</code> im <em>Projektmappen-Explrer</em> weiter auf, dann siehst du zum einen die Klasse <code class="language-plaintext highlighter-rouge">MainWindow</code>, aber auch die darin enthaltenen Attribute (Microsoft spricht hier von Feldern) und Methoden. Schaust du dir nun über einen Doppelklick den Quellcode der Methode <code class="language-plaintext highlighter-rouge">IntializeComponent</code> an, dann öffnet dir <em>Visual Studio</em> die Datei <code class="language-plaintext highlighter-rouge">MainWindow.g.i.cs</code>.</p>
<p>In den ersten Zeilen dieser Datei steht, dass es sich um eine automatisch generierte Datei handelt. Dieses kannst du sehen, wenn du dir den Inhalt der Datei anschaust, dann in der <code class="language-plaintext highlighter-rouge">MainWindow.xaml</code> ein Steuerelement hinzufügst und dir nochmals den Inhalt der Datei <code class="language-plaintext highlighter-rouge">MainWindow.g.i.cs</code> anschaust. Mit jeder Änderung der <code class="language-plaintext highlighter-rouge">*.xaml</code>-Datei, generiert <em>Visual Studio</em> die <code class="language-plaintext highlighter-rouge">*.g.i.cs</code> neu. Zwischen vielen (für uns) unwichtigen Informationen kannst du sehen, dass in dieser Datei die tatsächlichen Instanzen der Steuerelemente angelegt werden. Hier ein Beispiel:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#line 36 "..\..\..\MainWindow.xaml"
</span><span class="p">[</span><span class="n">System</span><span class="p">.</span><span class="n">Diagnostics</span><span class="p">.</span><span class="n">CodeAnalysis</span><span class="p">.</span><span class="nf">SuppressMessageAttribute</span><span class="p">(</span><span class="s">"Microsoft.Performance"</span><span class="p">,</span> <span class="s">"CA1823:AvoidUnusedPrivateFields"</span><span class="p">)]</span>
<span class="k">internal</span> <span class="n">System</span><span class="p">.</span><span class="n">Windows</span><span class="p">.</span><span class="n">Controls</span><span class="p">.</span><span class="n">Button</span> <span class="n">kaestchen_0_0</span><span class="p">;</span>
</code></pre></div></div>
<p>Mit diesem Quellcode aus meiner <code class="language-plaintext highlighter-rouge">MainWindow.g.i.cs</code> wird nun der <code class="language-plaintext highlighter-rouge">Button</code> mit dem Bezeichner <code class="language-plaintext highlighter-rouge">kaestchen_0_0</code> angelegt. Für das weitere Verständnis wichtig ist noch in welcher Klasse diese Instanz angelegt wird:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">TicTacToeWPF</span> <span class="p">{</span>
<span class="c1">/// <summary></span>
<span class="c1">/// MainWindow</span>
<span class="c1">/// </summary></span>
<span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">MainWindow</span> <span class="p">:</span> <span class="n">System</span><span class="p">.</span><span class="n">Windows</span><span class="p">.</span><span class="n">Window</span><span class="p">,</span> <span class="n">System</span><span class="p">.</span><span class="n">Windows</span><span class="p">.</span><span class="n">Markup</span><span class="p">.</span><span class="n">IComponentConnector</span> <span class="p">{</span>
<span class="c1">// den weiteren Quellcode lass ich aus platzgründen weg.</span>
</code></pre></div></div>
<p>Setzt du nun die einzelnen Puzzleteile zusammen, dann siehst du, dass ein Teil der Klasse <code class="language-plaintext highlighter-rouge">MainWindow</code> in der Datei <code class="language-plaintext highlighter-rouge">MainWindow.xaml.cs</code> definiert ist und ein weiterer Teil dieser Klasse in der Datei <code class="language-plaintext highlighter-rouge">MainWindow.g.i.cs</code>. Da in beiden Klassen das Schlüsselwort <code class="language-plaintext highlighter-rouge">partial</code> verwendet wird, weiß der <em>Compiler</em> nun, dass es sich um eine Klasse handelt die in 2 Dateien definiert ist.</p>
<p>Fazit:</p>
<ol>
<li>Es ist elementar, dass du verstehst, dass jedes Element (sowohl <em>Root Element</em> wie auch alle darin enthaltenen <em>Elemente</em>) letztlich im <em>C#</em>-Quellcode als Instanzen der jeweiligen Klassen angelegt werden.</li>
<li>Jedes Steuerelement aus einer <em>XAML</em>-Datei wird automatisch als Attribut im umgebenden <em>Root Element</em> im <em>C#</em>-Quellcode instanziiert.</li>
<li>Die Werte die du für Steuerelemente in einer <em>XAML</em>-Datei definierst, werden durch einen <em>Code-Generator</em> letztlich an die Instanzen (siehe 2.) übergeben.</li>
</ol>
<div class="subscribe-notice">
<h5>Hast du die Schnauze voll von Theorie?</h5>
<h5>Melde dich jetzt für den kostenlosen WPF Übungskurs an:</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Los gehts >></a>
</div>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/xaml-code-behind/">XAML, *.g.i.cs und code-behind in WPF</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am April 02, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/konfigurationen-platformen-visual-studio2020-04-01T10:13:09+02:002020-04-01T10:13:09+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Wenn du dir die Oberfläche von <em>Visual Studio</em> (insbesondere rund um den <code class="language-plaintext highlighter-rouge">Starten</code> Button) schon etwas genauer angesehen hast, dann bist du vielleicht über die <code class="language-plaintext highlighter-rouge">Kombobox</code> mit dem Inhalt <strong><em>Debug</em></strong> gestolpert. Das ist eine von 2 Standardkonfigurationen für die Projektmappe. Neben <em>Debug</em> gibt es in der Kombobox noch die Möglichkeit <strong><em>Release</em></strong> und <strong><em>Konfigurations-Manager</em></strong> auszuwählen.</p>
<p>Über <em>Debug</em> und <em>Release</em> kannst du u.a. steuern wie gut der <em>Debugger</em> deine Anwendung ausführen kann. Mit <em>Debug</em> werden die für den <em>Debugger</em> notwendigen Informationen vom <em>Compiler</em> erzeugt und der erzeugte <strong>Binärcode ist nicht optimiert</strong>. Verwendest du jedoch <em>Release</em>, dann versucht der <em>Compiler</em> einiges an Optimierungen für deinen Code umzusetzen und damit ist an einigen Stellen das Debugging nicht mehr ohne weiteres möglich.</p>
<p>Etwas mehr Details zum Thema <em>Binärcode</em> und was der <em>Compiler</em> mit dem Quellcode macht habe ich <a href="https://youtu.be/xhD1HCVj5V0?t=1783">an dieser Stelle</a> im <a href="https://youtu.be/xhD1HCVj5V0?t=1783">Visual Studio 2019 Tutorial</a> erklärt.</p>
<p>Die von <em>Visual Studio</em> verwendeten <em>Compiler</em> sind bei der Optimierung von Code ziemlich gut. Daher empfehle ich auch, dass du deinen Quellcode so schreibst, dass er <strong>aussagekräftig und gut lesbar</strong> ist. Häufig bekomme ich zuhören, dass beispielsweise durch die intensive Verwendung von Methoden die Anwendung langsam wird. Das ist definitiv nicht der Fall. Wenn du die verwendete Konfiguration auf <em>Release</em> stellst, dann wird an vielen Stellen der Code aus einer Methode genommen und direkt in die aufrufende Methode kopiert (das wird als <em>Inlining</em> bezeichnet). Dabei entscheiden die Compiler anhand verschiedenster Parameter wo eine solche Optimierung Sinn macht und wo nicht.</p>
<p>Der letzte Eintrag ist dann <strong><em>Konfigurationsmanager</em></strong>. Dieses ist ein separates Fenster in dem du für jedes <em>Projekt</em> einer <em>Projektmappe</em> festlegen kannst welche Konfiguration verwendet wird und auch für welche <em>Platform</em> das <em>Projekt</em> übersetzt werden soll. Neben den bereits vordefinierten Konfigurationen kannst du hier bei Bedarf auch eigene erstellen.</p>
<p>Bleibt noch die Frage was ist mit <em>Platform</em> gemeint und <strong>wofür steht <em>Any CPU</em>?</strong> Auch hier gibt es wie beim Thema <em>Optimierung</em> viele Details. Für den Start solltest du dir erstmal merken, dass <em>Any CPU</em> die “zuverlässigste” Variante ist. Mit <em>Any CPU</em> wird deine Anwendung so kompiliert, dass sie nach Möglichkeit als 64-Bit Prozess ausgeführt werden kann und wechselt zurück zu 32-Bit, wenn nur dieser Modus verfügbar ist (für weitere Optionen siehe <a href="https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/compiler-options/platform-compiler-option">hier</a>). Die gängigen Alternativen sind <em>x64</em> mit denen deine Anwendung nur als 64-Bit Prozess ausgeführt wird (und somit nicht als 32-Bit Prozess laufen kann) und <em>x86</em> womit deine Anwendung nur als 32-Bit Prozess ausgeführt wird.</p>
<p>In einigen Fällen musst du die Konfiguration explizit auf <em>x86</em> oder <em>x64</em> setzen. Das kann beispielweise dann der Fall sein, wenn du externe Bibliotheken einbindest die nur in einer bestimmten Version verfügbar sind. Womit wir auch schon beim nächsten Thema sind.</p>
<p><em>Tipp für Fortgeschrittene: Möchtest du dich intensiver mit dem Thema Debug, Release und deren Bedeutung für das Debugging beschäftigen, dann kann ich dir <a href="https://benhall.io/c-debug-vs-release-builds-and-debugging-in-visual-studio-from-novice-to-expert-in-one-blog-article/">diesen Artikel empfehlen</a>. Er ist allerdings auf Englisch.</em></p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/konfigurationen-platformen-visual-studio/">Visual Studio für Einsteiger: Debug, Release und AnyCPU</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am April 01, 2020.</p>
https://www.lernmoment.de/alle/projekt-auf-github-veroeffentlichen2021-03-10 06:00:00 +0100T00:00:00-00:002020-03-28T06:00:00+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<blockquote>
<p><strong>WICHTIG:</strong> Aufgrund einer neuen Oberfläche für die Bedienung von Git in Visual Studio 2019 (ab Version 16.8) ist dieser Artikel nur für ältere Versionen von Visual Studio 2019 relevant. Eine Aktualisierung dieses Artikels folgt demnächst. Das einfache Klonen eines Projektes mit der neuen Oberfläche habe ich bereits <a href="/alle/projekt-klonen-von-github/">hier</a> beschrieben.</p>
</blockquote>
<p>In <a href="/alle/git-mit-visual-studio-2019/">Versionskontrolle mit Git und Visual Studio 2019</a> habe ich dir gezeigt, wie du dein C# Projekt in <em>Visual Studio 2019</em> mit <em>git</em> verwalten kannst. Im nächsten Schritt gibt es viele Gründe dein Projekt auch auf <em>GitHub</em> zu bringen:</p>
<ul>
<li>Du kann von mir <a href="https://youtu.be/2gNVyMGfZTI">Rückmeldung zu deinem Projekt</a> bekommen</li>
<li>Dein Projekt als <em>Open Source Projekt</em> anbieten</li>
<li>Einfach ein Backup deines Projektes in einer “Cloud” speichern</li>
<li>Mit anderen (die du explizit einlädst) an deinem privaten Projekt arbeiten</li>
<li>Dein Projekt strukturiert bearbeiten & planen mit <em>Issues</em> und <em>Projects</em> auf <em>GitHub</em></li>
</ul>
<p>und natürlich viele weitere 😁!</p>
<p>In dieser Kurzanleitung zeige ich dir die wichtigsten Schritte um mit <em>Visual Studio</em></p>
<ol>
<li>die <em>GitHub for Visual Studio - Erweiterung</em> zu installieren</li>
<li>dein Projekt auf <em>GitHub</em> zubringen und</li>
<li>kontinuierlich Commits zwischen <em>Visual Studio</em> und <em>GitHub</em> zu synchronisieren</li>
</ol>
<p>Bevor du jedoch startest, sollte dir klar sein was genau die Unterschiede zwischen <em>git</em> und <em>GitHub</em> sind. Ich habe da mal was vorbereitet 😉: <a href="https://youtu.be/V_IDzTNA_ns">GitHub ist nicht git - was dann?</a>.</p>
<h2 id="1---github-erweiterung-in-visual-studio-installieren">1 - GitHub Erweiterung in Visual Studio installieren</h2>
<p>Bevor du anfängst solltest du dir in <em>Visual Studio</em> die <em>GitHub-Extension</em> installieren. Sie erleichtert das Zusammenspiel von <em>Visual Studio</em> und <em>GitHub</em> erheblich.</p>
<p><em>Visual Studio Extensions</em> sind häufig kostenlos und es gibt einen <a href="https://marketplace.visualstudio.com">umfangreichen Markplatz</a> dafür. Am einfachsten kannst du eine <em>Extension</em> jedoch direkt in <em>Visual Studio</em> installieren. Öffnest du den <em>Extensions verwalten</em> Dialog, siehst du im Bereich <em>Installiert</em> welche <em>Extensions</em> du bereits installiert hast (einige installiert <em>Visual Studio</em> bereits während der Installation). Ein Häkchen im grünen Kreis zeigt, dass eine <em>Extension</em> installiert ist.</p>
<p>Das folgende Bild und die nachfolgenden Schritte zeigen dir genau wie du die <em>GitHub Extension for Visual Studio</em> installieren kannst:</p>
<p><img src="https://www.lernmoment.de/images/github-mit-vs2019/vs-erweiterungen-verwalten.jpg" alt="GitHub Extension installieren" /></p>
<p><strong>Die wichtigsten Schritte:</strong></p>
<ol>
<li><em>Erweiterungen</em> verwalten <code class="language-plaintext highlighter-rouge">Erweiterungen -> Erweiterungen verwalten...</code></li>
<li>auf <em>Online</em> klicken</li>
<li>im Suchfeld oben rechts nach <em>GitHub</em> suchen</li>
<li><em>Extension</em> runterladen <code class="language-plaintext highlighter-rouge">"Download" Button an "GitHub for Visual Studio" drücken</code></li>
<li><em>Visual Studio</em> neustarten:</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- Alle Visual Studio Fenster schließen,
- im "VSIX Installer"-Dialog auf "Modify" (bzw. "Ändern") klicken und
- Visual Studio wieder starten
</code></pre></div></div>
<h2 id="2---projekt-auf-github-veröffentlichen">2 - Projekt auf GitHub veröffentlichen</h2>
<p>Sobald du die <em>GitHub for Visual Studio Erweiterung</em> installiert hast, kannst du auch schon dein Projekt auf <em>GitHub</em> veröffentlichen. Eine weitere Voraussetzung dafür ist, dass du dein Projekt bereits der Versionsverwaltung hinzugefügt hast. Das habe ich bereits <a href="/alle/git-mit-visual-studio-2019/">hier</a> beschrieben.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/github-mit-vs2019/sync-tab-oeffnen.jpg" alt="Änderungen-Seite im Team-Explorer" /></p>
<p>Sowohl das Hinzufügen deines Projektes wie auch das spätere Synchronisieren (siehe nächsten Schritt) machst du über den <em>Team-Explorer</em> in <em>Visual Studio</em>. Diesen findest üblicherweise in einem <em>Tab</em> neben dem <em>Projektmappen-Explorer</em> und im Menü <em>Ansicht</em>. Im <em>Team-Explorer</em> solltest du wie im Bild zu sehen in den Bereich <em>Sync</em> bzw. <em>Synchronisierung</em> wechseln.</p>
<p><strong>WICHTIG:</strong> Wenn du die <em>GitHub for Visual Studio Erweiterung</em> das erste Mal verwendest, musst du dich bei <em>GitHub</em> anmelden. Damit meine ich, dass du bereits einen <em>GitHub</em>-Account hast und dich nun mit deinem Benutzernamen und Passwort anmelden musst. Während dieser ersten Anmeldung werden deine Zugangsdaten gespeichert und ab dann kannst du direkt auf <em>GitHub</em> aus <em>Visual Studio</em> ohne weitere Anmeldung zugreifen. Die Möglichkeit zur Anmeldung bekommst du automatisch, wenn du den im folgenden beschriebenen Prozess zur Veröffentlichung umsetzt.</p>
<div class="subscribe-notice">
<h5>Lerne GitHub mit Visual Studio zu verwenden!</h5>
<a href="https://www.udemy.com/course/github-fuer-entwickler/?couponCode=GH_14-0121_LMDE" class="notice-button">Zum Online-Kurs "Einstieg in GitHub" >></a>
</div>
<p class="pull-right"><img src="https://www.lernmoment.de/images/github-mit-vs2019/projekt-veroeffentlichen.jpg" alt="Projekt auf GitHub veröffentlichen" /></p>
<p><strong>Die wichtigsten Schritte:</strong></p>
<p>Im Bereich <code class="language-plaintext highlighter-rouge">Synchronisierung</code> des <code class="language-plaintext highlighter-rouge">Team Explorer</code>:</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">In GitHub veröffentlichen</code> klicken</li>
<li>[optional] <code class="language-plaintext highlighter-rouge">Repositoryname</code> anpassen (<em>Visual Studio</em> verwendet automatisch den Projektnamen)</li>
<li>[optional, aber empfohlen] eine kurze (ein Satz) <code class="language-plaintext highlighter-rouge">Beschreibung</code> eingeben.</li>
<li>[optional] <code class="language-plaintext highlighter-rouge">Privates Repository</code> anwählen, wenn das Projekt nur für andere auf Einladung sichtbar sein soll.</li>
<li><code class="language-plaintext highlighter-rouge">Veröffentlichen</code> klicken</li>
</ol>
<p>Nun solltest du auf die <a href="https://github.com"><em>GitHub</em>-Seite</a> wechseln und schauen ob dein neues Projekt verfügbar ist. Es dauert einen Moment bis alles auf <em>GitHub</em> angelegt wird. Außerdem zeigt dir <em>Visual Studio</em> in der Statuszeile (unten rechts am Fensterrand), das <em>GitHub</em> Icon mit dem Namen des erstellten Verzeichnis auf <em>GitHub</em>. So sieht es nach der erfolgreichen Veröffentlichung aus:</p>
<p><img src="https://www.lernmoment.de/images/github-mit-vs2019/statusbar-mit-github.jpg" alt="Statusbar nach erfolgreicher Veröffentlichung" /></p>
<h2 id="3---commits-nach-github-pushen">3 - Commits nach GitHub <code class="language-plaintext highlighter-rouge">pushen</code></h2>
<p>Mit dem veröffentlichen deines Projektes werden einmalig alle bisherigen Änderungen (Commits) automatisch nach <em>GitHub</em> geschoben (engl. <em>push</em>).</p>
<p>Machst du nun weitere Änderungen und übergibst sie per <em>Commit</em> an <em>git</em>, werden sie <strong>nicht</strong> automatisch nach <em>GitHub</em> geschoben. Anstelle dessen kannst du entweder direkt beim <em>Commit</em> anstelle von <code class="language-plaintext highlighter-rouge">Commit für alle</code> die Option <code class="language-plaintext highlighter-rouge">Commit für alle und push</code> auswählen oder <strong>nachdem</strong> du einen oder mehrere <em>Commits</em> gemacht hast, wechselst du wieder zum <code class="language-plaintext highlighter-rouge">Sync</code> Bereich im <code class="language-plaintext highlighter-rouge">Team Explorer</code> und wählst dort <code class="language-plaintext highlighter-rouge">Push</code> aus.</p>
<p>Die <em>Statusbar</em> (unten rechts am Fensterrand) hilft dir dabei den Überblick über den Stand der Versionsverwaltung zubehalten. Hier nochmals ein Bild der <em>Statusbar</em> und anschließend die Erklärung was die einzelnen Informationen bedeuten:</p>
<p><img src="https://www.lernmoment.de/images/github-mit-vs2019/statusbar-erklaerung.jpg" alt="Statusbar Erklärung der Einträge" /></p>
<ol>
<li>Name des Projektes auf <em>GitHub</em> (wenn bereits auf <em>GitHub</em> veröffentlicht)</li>
<li>Anzahl der in <em>git</em> vorhandenen <em>Commits</em> die noch <strong>nicht</strong> auf <em>GitHub</em> geschoben wurden</li>
<li>Anzahl der geänderten Dateien die noch <strong>nicht</strong> per <em>Commit</em> abgegeben wurden</li>
<li>Name des Verzeichnis auf der Festplatte</li>
</ol>
<p>Hoffentlich hat dir diese Anleitung ein wenig geholfen beim Umgang mit <em>GitHub</em> und <em>Visual Studio</em>. Über jegliche Rückmeldung zu diesem Artikel würde ich mich sehr freuen:</p>
<p><a href="mailto:jan@lernmoment?subject=Frage%20zum%20Artikel:%20GitHub%20mit%20VisualStudio2019" class="notice-button">Fragen / Kommentare >></a></p>
<p>Viel Erfolg beim Veröffentlichen deines <em>VisualStudio</em>-Projektes auf <em>GitHub</em></p>
<p>Jan</p>
<p><a href="https://www.lernmoment.de/alle/projekt-auf-github-veroeffentlichen/">Synchronisiere dein Visual Studio 2019 Projekt mit GitHub</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 28, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/typkonvertierung-mit-cast2020-03-26T09:13:09+01:002020-03-26T09:13:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mmmmmoin und willkommen zu deinem LernMoment!</p>
<p>Bei der Entwicklung von Oberflächen (wie z.B. im <a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/tag1-spielfeld-anlegen-new-sub/">kostenlosen WPF-Übungskurs</a>) wie auch an einigen anderen Stellen, hast du einen Wert vom Datentyp X, aber du bräuchtest eigentlich Datentyp Y. Unter gewissen Randbedingungen hilft dir dann ein <em>Cast</em>. Hier ein Beispiel für das eigentliche Problem:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">void</span> <span class="nf">Kaestchen_0_0_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sender</span><span class="p">.</span><span class="n">Content</span> <span class="p">=</span> <span class="s">"X"</span><span class="p">;</span> <span class="c1">// IntelliSense zeigt Fehler CS1061 "object" enthält keine Defintion für "Content", ....</span>
<span class="c1">// es folgt weiterer Code, aber dieser ist für den cast nicht wichtig.</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In diesem Beispiel ist ein <em>EventHandler</em> (also letztlich eine Methode) mit dem <em>Parameter</em> <code class="language-plaintext highlighter-rouge">sender</code> vom Datentyp <code class="language-plaintext highlighter-rouge">object</code> definiert. Nur möchte ich in dem Beispiel gewisse Eigenschaften des <code class="language-plaintext highlighter-rouge">sender</code> verändern. Versuche ich direkt mit dem <code class="language-plaintext highlighter-rouge">sender</code> zu arbeiten, dann bekomme ich sofort den <a href="https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/compiler-messages/cs1061">Compiler-Fehler <code class="language-plaintext highlighter-rouge">CS1061</code></a>. Was also tun?</p>
<h3 id="typumwandlung-mit-explicit-cast">Typumwandlung mit explicit cast</h3>
<p>Bevor wir zur Lösung des vorherigen Beispiels kommen, möchte ich dir das Prinzip und die grundlegende Idee eines <em>Cast</em> erklären.</p>
<h4 id="typumwandlung-bei-werttypen-int-double-">Typumwandlung bei Werttypen (<code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">double</code>, …)</h4>
<p>Es gibt in C# doch einige Werttypen wie z.B. <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">short</code> oder auch <code class="language-plaintext highlighter-rouge">double</code> die sich in ihrem Wertebereich (und einigen anderen Aspekten) unterscheiden. Nehmen wir beispielsweise an, dass du die Variable <code class="language-plaintext highlighter-rouge">aShortValue</code> hast vom Datentyp <code class="language-plaintext highlighter-rouge">short</code>. Dieser Datentyp hat einen Wertebereich von <em>-32.768</em> bis <em>32.767</em> (siehe <a href="https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/builtin-types/integral-numeric-types">hier</a> für weitere Details). Möchtest du nun den Wert aus dieser Variable der Variablen <code class="language-plaintext highlighter-rouge">anIntValue</code> vom Datentyp <code class="language-plaintext highlighter-rouge">int</code> (Wertebereich von <em>-2.147.483.648</em> bis <em>2.147.483.647</em>) zuweisen, ist das kein Problem. Egal welchen Wert <code class="language-plaintext highlighter-rouge">aShortValues</code> besitzt, er passt immer in <code class="language-plaintext highlighter-rouge">anIntValue</code> rein. Der Wertebereich von <code class="language-plaintext highlighter-rouge">short</code> ist ja wesentlich kleiner als der von <code class="language-plaintext highlighter-rouge">int</code>. Bei einer solchen Zuweisung wird der <em>Datentyp</em> implizit von <code class="language-plaintext highlighter-rouge">short</code> nach <code class="language-plaintext highlighter-rouge">int</code> umgewandelt.</p>
<p>Wenn du das jedoch andersrum probierst (also <code class="language-plaintext highlighter-rouge">aShortValue = anIntValue</code>), dann bekommst du den Fehler <code class="language-plaintext highlighter-rouge">CS0266</code> vom <em>Compiler</em> angezeigt. Der <em>Compiler</em> weiß nämlich nicht welchen tatsächlichen Wert die Variable <code class="language-plaintext highlighter-rouge">anIntValue</code> zur Laufzeit haben wird. Daher schaut er auf die Datentypen und merkt, dass der Wertebereich von <code class="language-plaintext highlighter-rouge">int</code> wesentlich größer ist als der von <code class="language-plaintext highlighter-rouge">short</code>. Würde er die Zuweisung nun zulassen und <code class="language-plaintext highlighter-rouge">anIntValue</code> hätte beispielsweise den Wert <em>32.768</em> (also exakt um eins größer als der zulässige Wertebereich von <code class="language-plaintext highlighter-rouge">short</code>), dann gäbe es einen Überlauf. D.h. der Wert von <code class="language-plaintext highlighter-rouge">aShortValue</code> wäre dann <em>-32.768</em>. Er wird also plötzlich negativ. Dies kann dann potentiell alle möglichen anderen Fehler nach sich ziehen.</p>
<p>Um solche Fehler zu vermeiden, wurde <em>C#</em> als <em>statisch typisierte</em> Programmiersprache entworfen. D.h. du bekommst einen Compilerfehler, wenn du versuchst Datentypen in einander zu konvertieren bei denen ein Überlauf stattfinden kann. Hier das passende Beispiel zu der ganzen Theorie (probiere es ruhig als Konsolenanwendung aus):</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">short</span> <span class="n">aShortValue</span> <span class="p">=</span> <span class="m">10</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">anIntValue</span> <span class="p">=</span> <span class="n">aShortValue</span><span class="p">;</span> <span class="c1">//hier findet eine implizite Typumwandlung statt - OKAY!</span>
<span class="n">anIntValue</span> <span class="p">=</span> <span class="kt">short</span><span class="p">.</span><span class="n">MaxValue</span> <span class="p">+</span> <span class="m">1</span><span class="p">;</span>
<span class="c1">//aShortValue = anIntValue; //CS0266 - Der Typ "int" kann nicht implizit in "short" konvertiert werden.</span>
<span class="n">aShortValue</span> <span class="p">=</span> <span class="p">(</span><span class="kt">short</span><span class="p">)</span><span class="n">anIntValue</span><span class="p">;</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"anIntValue hat den Wert </span><span class="p">{</span><span class="n">anIntValue</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"aShortValue hat den Wert </span><span class="p">{</span><span class="n">aShortValue</span><span class="p">}</span><span class="s"> nach dem explicit Cast"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wie du in diesem Beispiel siehst, habe ich dann doch die Zuweisung <code class="language-plaintext highlighter-rouge">aShortValue = (short)anIntValue;</code> gemacht (ohne Fehler vom Comipler). Dies liegt an dem Zusatz <code class="language-plaintext highlighter-rouge">(short)</code>. Dabei handelt es sich um eine explizite Typumwandlung (oder <em>Cast</em> auf Englisch). Damit sage ich dem <em>Compiler</em>: “Ja ich weiß, dass das dumm ist, aber ich will es trotzdem machen!” Wenn du dir dann die Ausgabe in dem Beispiel ansiehst, siehst du auch prompt den Überlauf.</p>
<p>Es gibt verschiedene Szenarien in denen ein <em>Cast</em> angewendet wird. Üblicherweise dann, wenn du dir sicher bist, dass dadurch keine Informationen verloren gehen oder wenn der Informationsverlust für die weitere Bearbeitung nicht wichtig ist. Grundsätzlich solltest du jedoch bei jedem <em>Cast</em> misstrauisch sein.</p>
<p>Das grundlegende Konzept eines <em>Cast</em> sollte dir nun bekannt sein. Ein Zuweisung mithilfe einer expliziten Typumwandlung folgt immer dem gleichen Muster:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">short</span> <span class="n">aShortValue</span><span class="p">;</span>
<span class="c1">//Variable vom Zieltyp = (Zieltyp)Variable vom Ausgangstyp</span>
<span class="kt">double</span> <span class="n">aDoubleValue</span> <span class="p">=</span> <span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">aShortValue</span><span class="p">;</span>
</code></pre></div></div>
<h4 id="typumwandlung-bei-referenztypen">Typumwandlung bei Referenztypen</h4>
<p>Bei den Referenztypen, also Klassen, Arrays, <code class="language-plaintext highlighter-rouge">string</code> usw., gibt es sowohl implizite wie auch explizite Typumwandlung. Eine implizite Typumwandlung passiert, wenn du von einer <em>abgeleiteten Klasse</em> in eine <em>Basisklasse</em> konvertieren möchtest. Ein einfaches Beispiel könnte so aussehen:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MeineTolleKlasse</span> <span class="p">{</span> <span class="p">}</span> <span class="c1">// jede Klasse in C# erbt automatisch von object</span>
<span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">MeinTolleKlasse</span> <span class="n">eineVariable</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MeineTolleKlasse</span><span class="p">();</span>
<span class="c1">//im folgenden findet eine implizite Konvertierung statt</span>
<span class="kt">object</span> <span class="n">eineAndereVariable</span> <span class="p">=</span> <span class="n">eineVariable</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Durch die Definition der Klasse ist dem <em>Compiler</em> (während des kompilierens) klar, dass eine abgeleitete Klasse den Anteil jeder Basisklasse enthält. Somit kann es zu keinen Problemen kommen.</p>
<p>Versuchst du es jedoch in die andere Richtung (Umwandlung einer Variablen der Basisklasse in eine abgeleitete Klasse), dann bockt der <em>Compiler</em> wieder mit der Meldung <code class="language-plaintext highlighter-rouge">CS0266</code>. Die vollständige Fehlermeldung ist dann:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Fehler CS0266 Der Typ "object" kann nicht implizit in "MeineTolleKlasse" konvertiert werden.
Es ist bereits eine explizite Konvertierung vorhanden (möglicherweise fehlt eine Umwandlung).
</code></pre></div></div>
<p>Wie es bei einer “guten” Fehlermeldung sein sollte, gibt sie uns bereits einen Hinweis wie eine Behebung aussehen könnte. Machen wir wie uns geheißen und verwenden einen <em>Cast</em>, dann funktioniert das plötzlich ganz hervorragend:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MeineTolleKlasse</span> <span class="p">{</span> <span class="p">}</span> <span class="c1">// jede Klasse in C# erbt automatisch von object</span>
<span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">MeinTolleKlasse</span> <span class="n">eineVariable</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MeineTolleKlasse</span><span class="p">();</span>
<span class="kt">object</span> <span class="n">eineAndereVariable</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MeineTolleKlasse</span><span class="p">();</span>
<span class="c1">//im folgenden findet eine explizite Umwandlung statt</span>
<span class="n">eineVariable</span> <span class="p">=</span> <span class="p">(</span><span class="n">MeineTolleKlasse</span><span class="p">)</span><span class="n">eineAndereVariable</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Dafür das dieser <em>Cast</em> funktioniert, muss jedoch die Variable vom Typ der Basisklasse (in diesem Beispiel also <code class="language-plaintext highlighter-rouge">eineAndereVariable</code>) auf ein Objekt der abgeleiteten Klassen in die der Typ umgewandelt werden soll (in diesem Beispiel also <code class="language-plaintext highlighter-rouge">MeineTolleKlasse</code>) zeigen. Ist das nicht der Fall, dann gibt es eine <code class="language-plaintext highlighter-rouge">InvalidCastException</code>:</p>
<p><img src="https://www.lernmoment.de/images/typkonvertierung-mit-cast/invalid-cast-exception.jpg" alt="InvalidCastException" /></p>
<p>Wie du siehst, hebelst du also mit einem <em>Cast</em> die Typisierung aus. Wie bereits erwähnt solltest du dir also wirklich sicher sein was du tust und vor allem was <strong>zur Laufzeit</strong> in deiner Anwendung passieren kann, wenn du einen <em>Cast</em> verwendest.</p>
<p>Nach diesem umfangreichen Exkurs geht es nun zum Beispiel vom Anfang des Kapitels zurück. Dort gab es einen <em>EventHandler</em> in dem ich auf den <code class="language-plaintext highlighter-rouge">sender</code> zugreifen wollte:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">void</span> <span class="nf">Kaestchen_0_0_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Button</span> <span class="n">kaestchen</span> <span class="p">=</span> <span class="p">(</span><span class="n">Button</span><span class="p">)</span><span class="n">sender</span><span class="p">;</span>
<span class="n">kaestchen</span><span class="p">.</span><span class="n">Content</span> <span class="p">=</span> <span class="s">"X"</span><span class="p">;</span>
<span class="c1">// es folgt weiterer Code, aber dieser ist für den cast nicht wichtig.</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wie du siehst ist die Lösung ganz einfach. Ich verwende einen <em>Cast</em> um den <code class="language-plaintext highlighter-rouge">sender</code> vom Typ <code class="language-plaintext highlighter-rouge">object</code> in einen <code class="language-plaintext highlighter-rouge">Button</code> zu wandeln mit dem ich dann arbeiten kann. In diesem Fall habe ich mich für den <em>Cast</em> entschieden, weil ich die Gefahr einer <code class="language-plaintext highlighter-rouge">InvalidCastException</code> für vertretbar halte. Solange ich den <em>EventHandler</em> nicht an einem Steuerelemente anmelde welches nicht vom Typ <code class="language-plaintext highlighter-rouge">Button</code> ist, läuft alles ohne Probleme.</p>
<h3 id="as-operator-als-sicherheitsnetz-für-die-typkonvertierung"><code class="language-plaintext highlighter-rouge">as</code> Operator als Sicherheitsnetz für die Typkonvertierung</h3>
<p>Bisher habe ich immer auf die Gefahren des <em>Cast</em> hingewiesen. Um diese abzumildern, gibt es 2 weitere Operatoren in C# die dich bei Typumwandlungen unterstützen. Einer davon ist <code class="language-plaintext highlighter-rouge">as</code>.</p>
<p>Bevor ich in die Details gehe, gibt es eine Frage die du dir im Zusammenhang mit einem <em>Cast</em> eines <strong>Referenztypen</strong> stellen solltest:</p>
<p><em>Wie sicher ist es, dass die Referenz auf ein Objekt zeigt, welches vom gewünschten Typ ist?</em></p>
<p>Im Beispiel mit dem <code class="language-plaintext highlighter-rouge">Button</code> ist also die Frage wie sicher bin ich mir, dass hinter dem <code class="language-plaintext highlighter-rouge">sender</code> tatsächlich ein <code class="language-plaintext highlighter-rouge">Button</code> steckt? Dafür möchte ich 2 mögiche Antworten betrachten:</p>
<ol>
<li><em><code class="language-plaintext highlighter-rouge">sender</code> <strong>sollte</strong> auf einen <code class="language-plaintext highlighter-rouge">Button</code> zeigen</em> -> Wenn <code class="language-plaintext highlighter-rouge">sender</code> nicht auf einen <code class="language-plaintext highlighter-rouge">Button</code> zeigt ist irgendwas komplett falsch gelaufen. In diesem Beispiel könnte es sein, dass ich z.B. den <em>EventHandler</em> an einem anderen Steuerelement als einem <code class="language-plaintext highlighter-rouge">Button</code> anmelde. Das ist jedoch ein Fehler und die <code class="language-plaintext highlighter-rouge">InvalidCastException</code> die durch den <em>Cast</em> entsteht macht dieses eindeutig.</li>
<li><em><code class="language-plaintext highlighter-rouge">sender</code> <strong>könnte</strong> auf einen <code class="language-plaintext highlighter-rouge">Button</code> zeigen</em> -> Wenn ich beispielsweise eine Auflistung von verschiedenen Steuerelementen durchlaufe und möchte eine gewisse Aktion für alle <code class="language-plaintext highlighter-rouge">Button</code> darin ausführen, dann ist der <em>Cast</em> nicht das passenden Mittel. Ich gehe ja von Anfang an davon aus, dass auch etwas anderes als ein <code class="language-plaintext highlighter-rouge">Button</code> kommt und somit wäre eine <code class="language-plaintext highlighter-rouge">InvalidCastException</code> nicht der richtige Weg. Vorhang auf für den <code class="language-plaintext highlighter-rouge">as</code> Operator!</li>
</ol>
<p>Dazu ein weiteres Beispiel aus dem <a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/tag1-spielfeld-anlegen-new-sub/">kostenlosen WPF-Übungskurs</a>:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// "Spielfeld" ist eine Instanz vom Grid-Steuerelement</span>
<span class="k">private</span> <span class="kt">bool</span> <span class="nf">IstSpielfeldVoll</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="n">Spielfeld</span><span class="p">.</span><span class="n">Children</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Button</span> <span class="n">kaestchen</span> <span class="p">=</span> <span class="n">item</span> <span class="k">as</span> <span class="n">Button</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">kaestchen</span> <span class="p">==</span> <span class="k">null</span> <span class="p">||</span> <span class="n">kaestchen</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="nf">ToString</span><span class="p">()</span> <span class="p">==</span> <span class="s">""</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Der <code class="language-plaintext highlighter-rouge">as</code> Operator probiert (zur Laufzeit) ob eine Konvertierung möglich ist. Wenn ja, dann wird die Konvertierung durchgeführt und wenn nein, dann gibt der Operator <code class="language-plaintext highlighter-rouge">null</code> zurück. Somit ist es wichtig, dass nach der Verwendung des <code class="language-plaintext highlighter-rouge">as</code>-Operator, <strong>immer</strong> das Resultat auf <code class="language-plaintext highlighter-rouge">null</code> überprüft wird.</p>
<p>Im Gegensatz zum <em>Cast</em>, gibt es beim <code class="language-plaintext highlighter-rouge">as</code>-Operator keine <code class="language-plaintext highlighter-rouge">InvalidCastException</code>!</p>
<h3 id="alternative-is-operator-mit-pattern-matching-ab-c-70">Alternative: <code class="language-plaintext highlighter-rouge">is</code>-Operator mit Pattern-Matching (ab C# 7.0)</h3>
<p>2017 wurde die <a href="https://docs.microsoft.com/de-de/dotnet/csharp/whats-new/csharp-7">Sprachversion 7.0 von C#</a> eingeführt. Verwendest du <em>Visual Studio 2019</em> oder auch <em>Visual Studio 2017</em> in der aktuellsten Version, dann hast du immer mindestens die C#-Sprachversion 7.0 verfügbar. <a href="https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/configure-language-version">Hier ein Artikel auf Microsoft Docs</a> der dir die ganzen Details der Sprachversionen erklärt.</p>
<p>Ab C# 7.0 gibt es eine Funktionalität die nennt sich <em>Pattern Matching</em>. Ohne hier im Detail weiter darauf einzugehen (Thema für den nächsten Artikel ;), möchte ich dir diese Schreibweise noch zeigen. Sie ist dem <code class="language-plaintext highlighter-rouge">as</code>-Operator sehr ähnlich, aber sogar noch etwas kürzer:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// "Spielfeld" ist eine Instanz vom Grid-Steuerelement</span>
<span class="k">private</span> <span class="kt">bool</span> <span class="nf">IstSpielfeldVoll</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="n">Spielfeld</span><span class="p">.</span><span class="n">Children</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">item</span> <span class="k">is</span> <span class="n">Button</span> <span class="n">kaestchen</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">kaestchen</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="nf">ToString</span><span class="p">()</span> <span class="p">==</span> <span class="s">""</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wie su siehst wird durch den <code class="language-plaintext highlighter-rouge">is</code> Operator getestet ob <code class="language-plaintext highlighter-rouge">item</code> ein <code class="language-plaintext highlighter-rouge">Button</code> ist. Zusätzlich wird, <strong>wenn die Bedingung erfüllt ist</strong>, direkt eine Variable mit dem Namen <code class="language-plaintext highlighter-rouge">kaestchen</code> angelegt. <strong>Wichtig:</strong> Auf diese Weise ist die Variable <code class="language-plaintext highlighter-rouge">kaestchen</code> innerhalb der <code class="language-plaintext highlighter-rouge">foreach</code>-Schleife verfügbar. Es wird jedoch <strong>nicht</strong> garantiert, dass sie auch tatsächlich auf einen <code class="language-plaintext highlighter-rouge">Button</code> zeigt. <strong>Nur innerhalb</strong> der <code class="language-plaintext highlighter-rouge">if</code>-Abfrage kannst du dich darauf verlassen, dass du über die Variable einen <code class="language-plaintext highlighter-rouge">Button</code> ansprechen kannst. Außerhalb der <code class="language-plaintext highlighter-rouge">if</code>-Abfrage ist <code class="language-plaintext highlighter-rouge">kaestchen null</code>, wenn <code class="language-plaintext highlighter-rouge">item</code> kein <code class="language-plaintext highlighter-rouge">Button</code> ist.</p>
<p>Es gibt noch viele weitere spannende Punkte bezüglich Typkonvertierung, aber an dieser Stelle hast du erstmal das wichtigste im Kontext eines <em>Cast</em> gelernt. Einige der Informationen in diesem Artikel habe ich einer sehr guten Antwort von Jon Skeet auf StackOverflow entnommen. Wenn du etwas mehr ins Detail gehen möchtest, z.B. auch was die Performance angeht, dann kann ich dir <a href="https://stackoverflow.com/a/496167/5258906">diese Antwort (in Englisch)</a> absolut empfehlen.</p>
<p>Weiteres (auf Deutsch und von mir) dann in späteren Artikeln.</p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/typkonvertierung-mit-cast/">Was macht ein Cast (Typkonvertierung / Umwandlung) in C#?</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 26, 2020.</p>
https://www.lernmoment.de/alle/wpf-style-xaml-grundlagen2020-03-21T11:00:09+01:002020-03-21T11:00:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Eine von Microsofts Kernideen bei der Erstellung von <em>WPF</em> war die Trennung von Design und Entwicklung. Vielleicht hast du auch schon eine Anwendung gesehen bei der du dachtest: “Ein Entwickler sollte nicht die Gestaltung der Oberfläche übernehmen!” Dies ist zumindest einer der Gründe warum <em>WPF</em> sowohl Designer (mithilfe von <em>XAML</em> und <a href="https://docs.microsoft.com/en-us/visualstudio/xaml-tools/creating-a-ui-by-using-blend-for-visual-studio?view=vs-2019"><em>Blend for Visual Studio</em></a>) wie auch Entwickler ansprechen will.</p>
<p><em>WPF</em> bietet für Designer (oder design affine Entwickler wie uns ;) fast uneingeschränkte Möglichkeiten das Aussehen sämtlicher Steuerelemente zu verändern. Eine ganz triviale Einstellung ist beispielsweise die Hintergrundfarbe eines <code class="language-plaintext highlighter-rouge">Button</code> zu ändern:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"startButton"</span> <span class="na">Content=</span><span class="s">"Start"</span> <span class="na">Background=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
</code></pre></div></div>
<p>Natürlich könntest du auch etwas wagen und deinem <code class="language-plaintext highlighter-rouge">Button</code> einen Farbverlauf spendieren (denk aber dran das Entwickler häufig nicht die besten Designer sind ;):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"startButton"</span> <span class="na">Content=</span><span class="s">"Start"</span><span class="nt">></span>
<span class="nt"><Button.Background></span>
<span class="nt"><LinearGradientBrush></span>
<span class="nt"><GradientStop</span> <span class="na">Offset=</span><span class="s">"0.0"</span> <span class="na">Color=</span><span class="s">"#00A8C6"</span> <span class="nt">/></span>
<span class="nt"><GradientStop</span> <span class="na">Offset=</span><span class="s">"1.0"</span> <span class="na">Color=</span><span class="s">"#F9F2E7"</span> <span class="nt">/></span>
<span class="nt"></LinearGradientBrush></span>
<span class="nt"></Button.Background></span>
<span class="nt"></Button></span>
</code></pre></div></div>
<p>Möchtest du jedoch viele <code class="language-plaintext highlighter-rouge">Buttons</code> in dieser Art anpassen (wie z.B. im kostenlosen <a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/">WPF-Übungskurs</a>), dann führt das zu ziemlich viel kopieren und redudantem XAML-Code. Daher gibt es in WPF den <code class="language-plaintext highlighter-rouge">Style</code>.</p>
<p><strong>Merke:</strong> Mit einem <code class="language-plaintext highlighter-rouge">Style</code> kannst du das Aussehen von Steuerelementen verändern. Dabei kann ein <code class="language-plaintext highlighter-rouge">Style</code> an zentraler Stelle zur Verfügung gestellt werden und nach verschiedenen Kriterien den existierenden Steuerelementen zugewiesen werden.</p>
<h3 id="wie-ist-ein-style-aufgebaut">Wie ist ein <code class="language-plaintext highlighter-rouge">Style</code> aufgebaut?</h3>
<p>Das Aussehen von Steuerelementen wird über ihre Eigenschaften bestimmt. Ein Beispiel ist der <code class="language-plaintext highlighter-rouge">Background</code> den ich dir in den Beispielen in der Einführung bereits gezeigt habe. Das <em>XAML</em>-Element für einen <code class="language-plaintext highlighter-rouge">Style</code> ist erstmal total unspektakulär: <code class="language-plaintext highlighter-rouge"><Style> </Style></code>. Innerhalb des <code class="language-plaintext highlighter-rouge"><Style></code>-Elements kannst du mithilfe des <code class="language-plaintext highlighter-rouge"><Setter></code>-Elements jeweils eine Eigenschaft auf einen spezifischen Wert setzen:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Style></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Button.Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
</code></pre></div></div>
<p>Mit diesem <code class="language-plaintext highlighter-rouge">Style</code> wird also der Hintergrund auf das “LernMoment-Türkis” gesetzt. Natürlich kannst du auch den Farbverlauf so umsetzen. Dazu nimmst du den <code class="language-plaintext highlighter-rouge">Value</code> aus dem Einzeiler raus und definierst ihn innerhalb des <code class="language-plaintext highlighter-rouge">Setter</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Style></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Button.Background"</span><span class="nt">></span>
<span class="nt"><Setter.Value></span>
<span class="nt"><LinearGradientBrush></span>
<span class="nt"><GradientStop</span> <span class="na">Offset=</span><span class="s">"0.0"</span> <span class="na">Color=</span><span class="s">"#00A8C6"</span> <span class="nt">/></span>
<span class="nt"><GradientStop</span> <span class="na">Offset=</span><span class="s">"1.0"</span> <span class="na">Color=</span><span class="s">"#F9F2E7"</span> <span class="nt">/></span>
<span class="nt"></LinearGradientBrush></span>
<span class="nt"></Setter.Value></span>
<span class="nt"></Setter></span>
<span class="nt"></Style></span>
</code></pre></div></div>
<p>Anstelle des <code class="language-plaintext highlighter-rouge">Setter</code> gibt es noch einige weitere spannende Elemente die du innerhalb eines <code class="language-plaintext highlighter-rouge">Style</code> verwenden kannst. Das ist jedoch Futter für einen weiteren Artikel.</p>
<p>Da du ein aufmerksamer Leser bist, hast du dich bestimmt schon gefragt wieso ich die <code class="language-plaintext highlighter-rouge">Property</code> im <code class="language-plaintext highlighter-rouge">Setter</code> auf <code class="language-plaintext highlighter-rouge">Button.Background</code> und nicht einfach <code class="language-plaintext highlighter-rouge">Background</code> gesetzt habe. Um diese Frage zu lösen schauen wir uns erstmal an wie ein <code class="language-plaintext highlighter-rouge">Style</code> einem Steuerelement zugewiesen wird.</p>
<h3 id="einen-definierten-style-zuweisen">Einen definierten <code class="language-plaintext highlighter-rouge">Style</code> zuweisen</h3>
<p>Grundsätzlich gibt es 2,5 Möglichkeiten wie du definierst welches Steuerelement welchen <code class="language-plaintext highlighter-rouge">Style</code> bekommt:</p>
<ol>
<li>Zuweisung zu allen Steuerelementen eines <code class="language-plaintext highlighter-rouge">TargetType</code></li>
<li>Explizite Zuweisung mit <code class="language-plaintext highlighter-rouge">x:Key</code></li>
</ol>
<p>Okay, das sind nun nur 2. Was ist also mit der 0,5? Ganz einfach:</p>
<blockquote>
<p><strong>Merke:</strong> Unabhängig vom verwendeten <code class="language-plaintext highlighter-rouge">Style</code> hat die Definition an einem Steuerelement immer vorang!</p>
</blockquote>
<p>Definierst du also den <code class="language-plaintext highlighter-rouge">Background</code> über einen <code class="language-plaintext highlighter-rouge">Style</code> als rot, weist diesen <code class="language-plaintext highlighter-rouge">Style</code> einem <code class="language-plaintext highlighter-rouge">Button</code> zu und änderst an dem <code class="language-plaintext highlighter-rouge">Button</code> den <code class="language-plaintext highlighter-rouge">Background</code> auf weiß, dann wird der Hintergrund des <code class="language-plaintext highlighter-rouge">Button</code> weiß sein.</p>
<p>Nun schauen wir uns jedoch die ersten beiden Möglichkeiten im Detail an.</p>
<h4 id="allgemeine-zuweisung-per-targettype">Allgemeine Zuweisung per <code class="language-plaintext highlighter-rouge">TargetType</code></h4>
<p>Möchtest du alle Steuerelemente eines Typs (z.B. <code class="language-plaintext highlighter-rouge">Button</code> oder <code class="language-plaintext highlighter-rouge">Label</code>) mit dem gleichen Aussehen gestalten, dann verwendest du den <code class="language-plaintext highlighter-rouge">TargetType</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Style</span> <span class="na">TargetType=</span><span class="s">"Button"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
</code></pre></div></div>
<p>Mit dieser Definition bekommt einfach jeder <code class="language-plaintext highlighter-rouge">Button</code> im Geltungsbereich (dazu gleich mehr) des <code class="language-plaintext highlighter-rouge">Style</code> den türkisenen Hintergrund. Du kannst also einfach einen <code class="language-plaintext highlighter-rouge">Button</code> (z.B. in einem <code class="language-plaintext highlighter-rouge">Grid</code>) anlegen und dieser wird dann automatisch entsprechend des <code class="language-plaintext highlighter-rouge">Style</code> dargestellt:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Grid></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Drück mich!"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Wenn du dir den <code class="language-plaintext highlighter-rouge">Setter</code> genau ansiehst, dann merkst du, dass dort plötzlich <code class="language-plaintext highlighter-rouge">Background</code> steht und nicht <code class="language-plaintext highlighter-rouge">Button.Background</code>. Das liegt daran, dass nun klar ist, dass dieser <code class="language-plaintext highlighter-rouge">Style</code> nur für <code class="language-plaintext highlighter-rouge">Button</code> verwendet wird. Der Compiler kann also überprüfen ob der <code class="language-plaintext highlighter-rouge">Button</code> eine Eigenschaft <code class="language-plaintext highlighter-rouge">Background</code> hat (was er hat) und alles ist gut.</p>
<p>Im vorherigen Beispiel wurde kein <code class="language-plaintext highlighter-rouge">TargetType</code> angegeben und somit weiß der Compiler nicht auf was für eine Klasse sich die Eigenschaft bezieht. Dazu mehr beim Thema <code class="language-plaintext highlighter-rouge">x:Key</code>.</p>
<h4 id="explizite-zuweisung-per-xkey">Explizite Zuweisung per <code class="language-plaintext highlighter-rouge">x:Key</code></h4>
<p>Nicht immer ist es sinnvoll alle Instanzen eines Steuerelements gleich zu gestalten. Vielleicht möchtest du jeden <em>Ok</em>-<code class="language-plaintext highlighter-rouge">Button</code> speziell hervorheben. Dann kannst du einen <code class="language-plaintext highlighter-rouge">Style</code> mit einem eindeutigen Schlüssel definieren:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Style</span> <span class="na">x:Key=</span><span class="s">"okStyle"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Button.Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
</code></pre></div></div>
<p>Nun reicht es jedoch nicht mehr aus einfach nur einen <code class="language-plaintext highlighter-rouge">Button</code> anzulegen, sondern du musst explizit sagen, dass dieser den <code class="language-plaintext highlighter-rouge">Style</code> bekommen soll:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Grid></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Ok"</span> <span class="na">Style=</span><span class="s">"{StaticResource okStyle}"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">Content=</span><span class="s">"Drück mich!"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>So wird also der erste <code class="language-plaintext highlighter-rouge">Button</code> mit türkisenem Hintergrund dargestellt und der zweite Button ganz normal.</p>
<p>In dieser Art der Zuweisung ist allerdings für den Compiler nicht ersichtlich welchem Steuerelement der <code class="language-plaintext highlighter-rouge">Style</code> zugewiesen wird. Damit kann er auch nicht überprüfen ob es die entsprechenden Eigenschaften im <code class="language-plaintext highlighter-rouge">Style</code> überhaupt am Steuerelement gibt.</p>
<p>Verwendest du also diese explizite Art der Zuweisung, dann musst du bei der <code class="language-plaintext highlighter-rouge">Property</code> nicht nur den Namen der Eigenschaft angeben, sondern auch den Klassennamen des Steuerelements (also z.B. <code class="language-plaintext highlighter-rouge">Button.Background</code>).</p>
<p><strong>Pro-Tipp:</strong> Manchmal möchtest du vielleicht das Aussehen verschiedener Steuerelemente beeinflussen die auch alle eine gewisse Eigenschaft haben. Dann kannst du in der Vererbungshierarchie der Steuerelemente nach oben gehen. Viele Steuerelemente werden beispielsweise von der Klasse <code class="language-plaintext highlighter-rouge">Control</code> abgeleitet. Wenn du die Eigenschaften der Klasse <code class="language-plaintext highlighter-rouge">Control</code> anschaust, dann siehst du, dass es dort beispielsweise <code class="language-plaintext highlighter-rouge">Background</code> und auch viele <code class="language-plaintext highlighter-rouge">Font</code>-bezogene Eigenschaften gibt. Möchtest du also beispielsweise einen Style erstellen der sowohl für <code class="language-plaintext highlighter-rouge">Button</code> wie auch <code class="language-plaintext highlighter-rouge">Label</code> verwendet werden kann, dann würde das so aussehen:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Style</span> <span class="na">x:Key=</span><span class="s">"proStyle"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Control.Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
</code></pre></div></div>
<p>Über den Schlüssel <code class="language-plaintext highlighter-rouge">proStyle</code> kannst du nun den verschiedesten Steuerelementen einen türkisenen Hintergrund verpassen.</p>
<h3 id="wo-ist-ein-style-verfügbar">Wo ist ein <code class="language-plaintext highlighter-rouge">Style</code> verfügbar?</h3>
<p>Eben habe ich bereits erwähnt, dass es einen Geltungsbereich für einen <code class="language-plaintext highlighter-rouge">Style</code> gibt. Der Ort an dem du einen <code class="language-plaintext highlighter-rouge">Style</code> definierst legt auch zugleich seinen Geltungsbereich fest:</p>
<ol>
<li>Lokal am Steuerelement - Es ist tatsächlich möglich an einem Steuerelement einen <code class="language-plaintext highlighter-rouge">Style</code> zu definieren. Dieser wäre dann auch nur für das jeweilige Steuerelement gültig. Daher ist es relativ sinnlos, weil du ein einzelnes Steuerelement viel leichter über seine Eigenschaften anpassen kannst als über <code class="language-plaintext highlighter-rouge">Style</code>, <code class="language-plaintext highlighter-rouge">Setter</code> usw.</li>
<li>Am umgebenden Container - Der visuelle Bereich einer <em>WPF</em>-Anwendung ist hierarchisch aufgebaut. Die oberste Ebene ist die <code class="language-plaintext highlighter-rouge">App</code>. Darin enthalten sind ein oder mehrere <code class="language-plaintext highlighter-rouge">Window</code>. Darin enthalten sind wiederum Steuerelement wie das <code class="language-plaintext highlighter-rouge">Grid</code> oder auch <code class="language-plaintext highlighter-rouge">StackPanel</code> die als Container weitere Steuerelemente enthalten. Auf jeder Ebene gibt es den <code class="language-plaintext highlighter-rouge">Resources</code> Bereich und in diesem kannst du einen <code class="language-plaintext highlighter-rouge">Style</code> definieren.</li>
</ol>
<p>Hier nun ein paar Beispiele für die Definition unseres <code class="language-plaintext highlighter-rouge">Style</code> auf unterschiedlichen Ebenen.</p>
<h4 id="app-in-appxaml"><code class="language-plaintext highlighter-rouge">App</code> in App.xaml</h4>
<p>In jedem <em>WPF</em>-Projekt gibt es die Datei <code class="language-plaintext highlighter-rouge">App.xaml</code>. Sie ist die oberste Ebene. Wenn du hier einen <code class="language-plaintext highlighter-rouge">Style</code> definierst ist dieser innerhalb deiner kompletten Anwendung verfügbar:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Application</span> <span class="na">x:Class=</span><span class="s">"TicTacToeWPF.App"</span>
<span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span>
<span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml"</span>
<span class="na">StartupUri=</span><span class="s">"MainWindow.xaml"</span><span class="nt">></span>
<span class="nt"><Application.Resources></span>
<span class="nt"><Style</span> <span class="na">TargetType=</span><span class="s">"Button"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
<span class="nt"></Application.Resources></span>
<span class="nt"></Application></span>
</code></pre></div></div>
<h4 id="window-zb-in-mainwindowxaml"><code class="language-plaintext highlighter-rouge">Window</code> z.B. in MainWindow.xaml</h4>
<p>Jedes <em>WPF</em>-Projekt hat mindestens ein <code class="language-plaintext highlighter-rouge">Window</code>. Definierst du einen <code class="language-plaintext highlighter-rouge">Style</code> an einem <code class="language-plaintext highlighter-rouge">Window</code> dann ist er “nur” innerhalb dieses Fensters verfügbar.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Window</span> <span class="na">x:Class=</span><span class="s">"TicTacToeWPF.MainWindow"</span>
<span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span>
<span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2006/xaml"</span>
<span class="na">xmlns:d=</span><span class="s">"http://schemas.microsoft.com/expression/blend/2008"</span>
<span class="na">xmlns:mc=</span><span class="s">"http://schemas.openxmlformats.org/markup-compatibility/2006"</span>
<span class="na">xmlns:local=</span><span class="s">"clr-namespace:TicTacToeWPF"</span>
<span class="na">mc:Ignorable=</span><span class="s">"d"</span>
<span class="na">Title=</span><span class="s">"LernMoments TicTacToe in WPF"</span> <span class="na">Height=</span><span class="s">"500"</span> <span class="na">Width=</span><span class="s">"500"</span><span class="nt">></span>
<span class="nt"><Window.Resources></span>
<span class="nt"><Style</span> <span class="na">x:Key=</span><span class="s">"türkiserButton"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Button.Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
<span class="nt"></Window.Resources></span>
<span class="nt"></Window></span>
</code></pre></div></div>
<h4 id="stackpanel-in-einem-grid-in-einem-window"><code class="language-plaintext highlighter-rouge">StackPanel</code> in einem <code class="language-plaintext highlighter-rouge">Grid</code> in einem <code class="language-plaintext highlighter-rouge">Window</code></h4>
<p>Möchtest du noch weiter runter gehen und den <code class="language-plaintext highlighter-rouge">Style</code> nur in einem Teil eines Fensters verwenden, dann kannst du dieses auch machen:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Grid></span>
<span class="nt"><StackPanel</span> <span class="na">x:Name=</span><span class="s">"ersterStack"</span><span class="nt">></span>
<span class="nt"><StackPanel.Resources></span>
<span class="nt"><Style</span> <span class="na">x:Key=</span><span class="s">"türkiserButton"</span><span class="nt">></span>
<span class="nt"><Setter</span> <span class="na">Property=</span><span class="s">"Button.Background"</span> <span class="na">Value=</span><span class="s">"#00A8C6"</span><span class="nt">/></span>
<span class="nt"></Style></span>
<span class="nt"></StackPanel.Resources></span>
<span class="nt"></StackPanel></span>
<span class="nt"><StackPanel</span> <span class="na">x:Name=</span><span class="s">"zweiterStack"</span><span class="nt">></span>
<span class="nt"></StackPanel.Resources></span>
<span class="nt"></StackPanel></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Mit dieser Definition ist der <code class="language-plaintext highlighter-rouge">Style</code> im <code class="language-plaintext highlighter-rouge">ersterStack</code> verfügbar, aber nicht im <code class="language-plaintext highlighter-rouge">zweiterStack</code>. Allerdings wird es wohl wirklich wenig Anwendungsfälle geben wo du diese Variante einsetzen kannst.</p>
<p>Möchtest du das hier gelernte direkt in die Praxis umsetzen? Dann probiere meinen WPF-Übungskurs aus. Schon in der 2. Einheit geht es um das Styling.</p>
<div class="subscribe-notice">
<h5>Melde dich jetzt für den kostenlosen WPF Übungskurs an:</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Los gehts >></a>
</div>
<p>So viel erstmal zu den absoluten Grundlagen im Bereich <code class="language-plaintext highlighter-rouge">Style</code>. Es gibt noch viel mehr spannende Funktionalitäten wie beispielsweise:</p>
<ul>
<li>Definition eines <code class="language-plaintext highlighter-rouge">Style</code> in einer separaten Datei (z.B. <code class="language-plaintext highlighter-rouge">MeinCoolerButtonStyle.xaml</code>) der dann auch zwischen verschiedenen Projekten ausgetauscht werden kann. Damit ist beispielsweise auch eine Art einheitliche “Design-Bibliothek” für alle Anwendungen in einer Firma realisierbar.</li>
<li>Änderung des Aussehens von Controls anhand von definierten Ereignissen oder Werten einer bestimmten Variable.</li>
<li>Animationen</li>
</ul>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/wpf-style-xaml-grundlagen/">Grundlagen vom WPF Style Element in XAML</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 21, 2020.</p>
https://www.lernmoment.de/alle/wpf-grid-panel-xaml-grundlagen2020-03-15T11:00:09+01:002020-03-15T11:00:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Jedes <code class="language-plaintext highlighter-rouge">Window</code> in einer <em>WPF-App</em> wird standardmäßig mit einem <code class="language-plaintext highlighter-rouge">Grid</code> erstellt. Wie die anderen <code class="language-plaintext highlighter-rouge">Panel</code> Steuerelemente auch, handelt es sich dabei um einen <code class="language-plaintext highlighter-rouge">Container</code>. Du benötigst in einem <code class="language-plaintext highlighter-rouge">Window</code> immer ein <code class="language-plaintext highlighter-rouge">Container</code> Steuerelement in welches du weitere Steuerelement “stecken” kannst.</p>
<p>Mit einem <code class="language-plaintext highlighter-rouge">Grid</code> kannst du:</p>
<ul>
<li>andere Steuerelemente in Tabellenform (also Zeilen und Spalten) anordnen</li>
<li>ein Steuerelement in eine spezifische Zelle setzen</li>
<li>ein Steuerelement über mehrere Zellen anordnen</li>
<li>mehrere Steuerelemente übereinander anordnen</li>
<li>sicherstellen, dass enthaltene Steuerelemente ihre Größe proportional anpassen</li>
</ul>
<p>Um dir die verschiedensten Möglichkeiten zu zeigen möchte ich <a href="https://github.com/LernMoment/wpf-tutorial-deutsch">hier</a> einen kleinen <em>WPF-YouTube-Player</em> entwickeln. So wird das gute Stück aussehen, wenn es fertig sind:</p>
<p><img src="https://www.lernmoment.de/images/wpf-youtube-player-grid-grundlagen.jpg" alt="Fertige WPF Oberfläche des WPF YouTube Player" /></p>
<p>Im folgenden zeige ich dir immer einzelne Ausschnitte vom <em>XAML</em> und erkläre dir was dadurch passiert. Du weißt nicht was <em>XAML</em> bedeutet und wo du es in Visual Studio 2019 eingibst? Dann kann ich dir <a href="https://youtu.be/ugji-_yWoRk?t=175">diesen praktischen und kostenlosen Einstieg in WPF</a> empfehlen.</p>
<p><strong>Quellcode:</strong> Den kompletten Quellcode zu dem Beispiel findest du <a href="https://github.com/LernMoment/wpf-tutorial-deutsch">hier</a>.</p>
<h3 id="allgemeine-einstellungen-am-grid">Allgemeine Einstellungen am Grid</h3>
<p>Bevor wir damit beginnen die einzelnen Spalten und Zeilen anzulegen und mit Steuerelementen zu füllen, will ich dir erstmal ein paar grundlegende Einstellungen am <code class="language-plaintext highlighter-rouge">Grid</code> zeigen.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einGrid"</span> <span class="na">Background=</span><span class="s">"Gainsboro"</span> <span class="na">ShowGridLines=</span><span class="s">"True"</span><span class="nt">></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Wie du sehen kannst habe ich für das <code class="language-plaintext highlighter-rouge">Grid</code> in dem Beispiel die folgenden Eigenschaften verwendet:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">x:Name="einGrid"</code> - wie bei allen <em>XAML</em> Elementen wird damit für dieses spezifische Steuerelemente ein Namen gesetzt mit dem wir später aus dem Quellcode das Steuerelement ansprechen können. Hier habe ich den sehr kreativen Namen <em>einGrid</em> gewählt.</li>
<li><code class="language-plaintext highlighter-rouge">Background="Gainsboro"</code> - Damit setzen wir die Hintergrundfarbe des Grids (in diesem Fall auf <code class="language-plaintext highlighter-rouge">Gainsboro</code>). Diese wird überall dort sichtbar wo kein Steuerelement platziert ist, oder ein Steuerelement teilweise durchsichtig ist. Das siehst du später z.B. beim <code class="language-plaintext highlighter-rouge">Label</code>. Im <em>XAML-Editor</em> werden dir bereits viele Farben vorgeschlagen und du kannst auch direkt <em>RGB</em>-Werte eingeben.</li>
<li><code class="language-plaintext highlighter-rouge">ShowGridLines="True"</code> - Damit wird definiert, dass gestrichelte Linien angezeigt werden. D.h. die Grenzen von Spalten und Zeilen werden damit visualisiert. Das ist meistens nur für Testanwendungen wie diese notwendig oder wenn du einen Fehler in deinem Layout suchst.</li>
</ul>
<p><em>Hinweis:</em> Solltest du den Drang verspüren wesentlich mehr Formatierung (z.B. unterschiedliche Farben für unterschiedliche Zellen oder Zeilen) einzufügen, bist du wahrscheinlich beim falschen Steuerelemente gelandet. Das <code class="language-plaintext highlighter-rouge">Grid</code> ist <strong>nicht</strong> zur Anzeige von Daten (dabei ist eine solche Formatierung ja wirklich hilfreich). Möchtest du Daten anzeigen und die Anzeige formatieren, dann solltest du besser das <code class="language-plaintext highlighter-rouge">DataGrid</code> verwenden.</p>
<h3 id="spalten-und-zeilen-für-das-grid-in-xaml-definieren">Spalten und Zeilen für das <code class="language-plaintext highlighter-rouge">Grid</code> in <em>XAML</em> definieren</h3>
<p>Wie gesagt ist das <code class="language-plaintext highlighter-rouge">Grid</code> ein <em>Container</em> und alles was du im <code class="language-plaintext highlighter-rouge">Grid</code> darstellen möchtest musst du zwischen <code class="language-plaintext highlighter-rouge"><Grid ...></code> und <code class="language-plaintext highlighter-rouge"></Grid></code> schreiben. Um dem <code class="language-plaintext highlighter-rouge">Grid</code> zusagen welche Spalten und Zeilen benötigt werden habe ich in der Beispielanwendung folgendes definiert:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einGrid"</span> <span class="na">Background=</span><span class="s">"Gainsboro"</span> <span class="na">ShowGridLines=</span><span class="s">"True"</span><span class="nt">></span>
<span class="nt"><Grid.ColumnDefinitions></span>
<span class="nt"><ColumnDefinition</span> <span class="na">Width=</span><span class="s">"Auto"</span><span class="nt">/></span>
<span class="nt"><ColumnDefinition</span> <span class="na">Width=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"><ColumnDefinition</span> <span class="na">Width=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"><ColumnDefinition</span> <span class="na">Width=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"><ColumnDefinition</span> <span class="na">Width=</span><span class="s">"Auto"</span><span class="nt">/></span>
<span class="nt"></Grid.ColumnDefinitions></span>
<span class="nt"><Grid.RowDefinitions></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"Auto"</span><span class="nt">/></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"Auto"</span><span class="nt">/></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"*"</span><span class="nt">/></span>
<span class="nt"><RowDefinition</span> <span class="na">Height=</span><span class="s">"Auto"</span><span class="nt">/></span>
<span class="nt"></Grid.RowDefinitions></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Zwischen <code class="language-plaintext highlighter-rouge"><Grid.ColumnDefintions></code> und <code class="language-plaintext highlighter-rouge"></Grid.ColumnDefintions></code> werden die einzelnen Spalten angelegt. Wie du hier siehst habe ich 5 Spalten verwendet. Für jede Spalte kannst du definieren wieviel Platz einer Spalte im Layout zugeordnet wird. Dabei kannst du folgende Werte verwenden:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Auto</code> - eine Spalte wird so Breit wie der in ihr enthaltene Inhalt benötigt. Dabei wird über alle Zeilen geschaut und der breiteste Inhalt verwendet.</li>
<li>Absoluter Wert (z.B. <code class="language-plaintext highlighter-rouge">Width="30"</code>) - die Spalte wird exakt so viele Pixel breit wie du angibst. In dem Beispiel also <em>30</em> Pixel</li>
<li><code class="language-plaintext highlighter-rouge">*</code> - Nachdem für ein Layout die Spalten mit <code class="language-plaintext highlighter-rouge">Auto</code> und <em>absoluter Wert</em> verwendet wurden, bleibt auf die gesamte Breite des <code class="language-plaintext highlighter-rouge">Grid</code> gesehen noch eine freie Fläche. Diese wird nun gleichmäßig zwischen allen Spalten aufgeteilt die Ihre Breite auf <code class="language-plaintext highlighter-rouge">*</code> gesetzt haben. In unserem Beispiel werden also die 2. bis 4. Spalte die exakt gleiche Breite haben. Wie breit sie genau sind hängt davon ab wieviel Platz die 1. und 5. Spalte einnehmen.</li>
</ul>
<p>Die Definition der Zeilen geht genau wie die der Spalten halt nur mit <code class="language-plaintext highlighter-rouge"><Grid.RowDefinitions></code> und <code class="language-plaintext highlighter-rouge"><RowDefinition></code>.</p>
<p><em>Hinweis:</em> für die “Größenangabe” <code class="language-plaintext highlighter-rouge">*</code> gibt es noch eine Erweiterung. Schreibst du bei einer Spalte (oder Zeile) eine Zahl vor den <code class="language-plaintext highlighter-rouge">*</code>, also z.B. <code class="language-plaintext highlighter-rouge">3*</code>, bedeutet das, dass diese Spalte dreimal soviel Platz bekommt wie eine Spalte die <code class="language-plaintext highlighter-rouge">*</code> gesetzt ist. Daraus ergibt sich, dass <code class="language-plaintext highlighter-rouge">*</code> die kurzschreibweise für <code class="language-plaintext highlighter-rouge">1*</code> ist.</p>
<h3 id="steuerelemente-den-zellen-zuweisen">Steuerelemente den Zellen zuweisen</h3>
<p>Nun könntest du einfach Steuerelemente in das <code class="language-plaintext highlighter-rouge">Grid</code> einfügen:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einGrid"</span> <span class="na">Background=</span><span class="s">"Gainsboro"</span> <span class="na">ShowGridLines=</span><span class="s">"True"</span><span class="nt">></span>
<span class="nt"><Grid.ColumnDefinitions></span>
<span class="c"><!--ColumnDefinition siehe oben --></span>
<span class="nt"></Grid.ColumnDefinitions></span>
<span class="nt"><Grid.RowDefinitions></span>
<span class="c"><!--RowDefinition siehe oben --></span>
<span class="nt"></Grid.RowDefinitions></span>
<span class="nt"><Label</span> <span class="na">Content=</span><span class="s">"Ein Text"</span><span class="nt">/></span>
<span class="nt"><Label</span> <span class="na">Content=</span><span class="s">"Ein anderer Text"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Dann siehst du allerdings, dass alles oben links in die erste Spalte und erste Zeile gesetzt wird. Um die verschiedenen Steuerelemente nun wirklich den einzelnen Zellen zuweisen zukönnen, musst du für jedes Steuerelement definieren in welcher Zeile und welcher Spalte es angezeigt werden soll:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Grid</span> <span class="na">x:Name=</span><span class="s">"einGrid"</span> <span class="na">Background=</span><span class="s">"Gainsboro"</span> <span class="na">ShowGridLines=</span><span class="s">"True"</span><span class="nt">></span>
<span class="nt"><Grid.ColumnDefinitions></span>
<span class="c"><!--ColumnDefinition siehe oben --></span>
<span class="nt"></Grid.ColumnDefinitions></span>
<span class="nt"><Grid.RowDefinitions></span>
<span class="c"><!--RowDefinition siehe oben --></span>
<span class="nt"></Grid.RowDefinitions></span>
<span class="c"><!--Zeile 0--></span>
<span class="nt"><Image</span> <span class="na">Source=</span><span class="s">"LernMomentIcon.png"</span> <span class="na">Grid.Column=</span><span class="s">"0"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="nt"><TextBlock</span> <span class="na">Text=</span><span class="s">"EinText"</span> <span class="na">Grid.Column=</span><span class="s">"1"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="c"><!--Zeile 1--></span>
<span class="nt"><Label</span> <span class="na">Content=</span><span class="s">"Öffne:"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="nt"><TextBox</span> <span class="na">x:Name=</span><span class="s">"YoutubeUrlTextBox"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"1"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"okButton"</span> <span class="na">Content=</span><span class="s">"Ok"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"4"</span><span class="nt">/></span>
<span class="nt"></Grid></span>
</code></pre></div></div>
<p>Die relevanten Eigenschaften sind also:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Grid.Column</code> - damit wird an einem Steuerelemente definiert in welcher <strong>Spalte</strong> es angezeigt werden soll. <strong>Wichtig:</strong> die erste Spalte (also ganz links) hat den Index 0!</li>
<li><code class="language-plaintext highlighter-rouge">Grid.Row</code> - damit wird an einem Steuerelemente definiert in welcher <strong>Zeile</strong> es angezeigt werden soll. <strong>Wichtig:</strong> die erste Zeile (also ganz oben) hat den Index 0!</li>
</ul>
<div class="subscribe-notice">
<h5>Hast du die Schnauze voll von Theorie?</h5>
<h5>Praxis mit dem Grid bekommst du im kostenlosen WPF-Übungskurs:</h5>
<a href="https://www.lernmoment.de/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/" class="notice-button">Erfahre mehr >></a>
</div>
<p>Insbesondere wenn du viele Steuerelemente in einem <code class="language-plaintext highlighter-rouge">Grid</code> hast, dann kann es also schon etwas unübersichtlich werden. Daher habe ich in diesem Beispiel auch per <em>XAML</em>-Kommentar (<code class="language-plaintext highlighter-rouge"><!--Zeile 0--></code>) festgehalten in welcher Zeile die folgenden Steuerelemente angezeigt werden. Für Visual Studio ist das zwar total egal, aber es hilft mir (mit ein wenig Disziplin ;) den Überblick zubehalten.</p>
<h3 id="zeilenübergreifendespaltenübergreifende-steuerelemente">Zeilenübergreifende/Spaltenübergreifende Steuerelemente</h3>
<p>Häufig, wie auch in diesem Beispiel, ist es notwendig, dass du einzelne Steuerelemente über mehrere Spalten und/oder mehrere Zeilen in das <code class="language-plaintext highlighter-rouge">Grid</code> einfügst. Dazu gibt es die Eigenschaften <code class="language-plaintext highlighter-rouge"><Grid.ColumnSpan></code> und <code class="language-plaintext highlighter-rouge"><Grid.RowSpan></code>. Wenn du dir nochmals das Bild vom Artikelanfang anschaust, siehst du, dass sowohl der <code class="language-plaintext highlighter-rouge">TextBlock</code> in der ersten Zeile, wie auch die <code class="language-plaintext highlighter-rouge">TextBox</code> in der zweiten Zeile über mehrere Zeilen gehen. Daraus ergibt sich folgende Definition:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!--Zeile 0--></span>
<span class="nt"><Image</span> <span class="na">Source=</span><span class="s">"LernMomentIcon.png"</span> <span class="na">Grid.Column=</span><span class="s">"0"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="nt"><TextBlock</span> <span class="na">Text=</span><span class="s">"Spielt YouTube Videos direkt in der Anwendung ab. Gib einfach die YouTube-URL ein und drücke 'Enter' oder klicke 'Ok'."</span>
<span class="na">Grid.Column=</span><span class="s">"1"</span> <span class="na">Grid.ColumnSpan=</span><span class="s">"4"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="c"><!--Zeile 1--></span>
<span class="nt"><Label</span> <span class="na">Content=</span><span class="s">"Öffne:"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"0"</span><span class="nt">/></span>
<span class="nt"><TextBox</span> <span class="na">x:Name=</span><span class="s">"YoutubeUrlTextBox"</span> <span class="na">VerticalAlignment=</span><span class="s">"Center"</span>
<span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"1"</span> <span class="na">Grid.ColumnSpan=</span><span class="s">"3"</span><span class="nt">/></span>
<span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"okButton"</span> <span class="na">Content=</span><span class="s">"Ok"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"4"</span><span class="nt">/></span>
</code></pre></div></div>
<p>Hier kannst du sehen, dass der <code class="language-plaintext highlighter-rouge">TextBlock</code> in der ersten Zeile mithilfe von <code class="language-plaintext highlighter-rouge">Grid.ColumnSpan="4"</code> den kompletten Platz (mit Ausnahme der ersten Spalte) einnimmt. Bei der <code class="language-plaintext highlighter-rouge">TextBox</code> in der zweiten Teile verwende ich <code class="language-plaintext highlighter-rouge">Grid.ColumnSpan="3"</code>, weil in der letzten Spalte noch der <code class="language-plaintext highlighter-rouge">Button</code> angezeigt werden soll.</p>
<p>Hier kannst du dir merken, dass du erst definierst in welcher Spalte/Zeile das Steuerelemente starten soll und dann gibst an, über wieviel Spalten/Zeilen das Steuerelement insgesamt gehen soll.</p>
<h3 id="margin---bitte-abstand-halten">Margin - Bitte Abstand halten</h3>
<p>Wenn du meine finale Version der <em>XAML</em>-Datei siehst, wirst du entdecken, dass ich an einigen Steuerelementen die Eigenschaft <code class="language-plaintext highlighter-rouge">Margin</code> verwendet habe. Diese Eigenschaft ist nicht spezifisch für das <code class="language-plaintext highlighter-rouge">Grid</code>, aber hilft dir auch hier das Layout zu verbessern. Nehmen wir z.B. die Definition des <code class="language-plaintext highlighter-rouge">okButton</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><Button</span> <span class="na">x:Name=</span><span class="s">"okButton"</span> <span class="na">Content=</span><span class="s">"Ok"</span> <span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"4"</span> <span class="na">Margin=</span><span class="s">"2,2,2,2"</span><span class="nt">/></span>
</code></pre></div></div>
<p>Hier der <code class="language-plaintext highlighter-rouge">Button</code> im fertigen Layout <strong>mit</strong> Margin:
<img src="https://www.lernmoment.de/images/wpf-youtube-player-okbutton-mit-margin.png" alt="Ok-Button des WPF YouTube Players mit Margin" /></p>
<p>Mit dieser Definition der <code class="language-plaintext highlighter-rouge">Margin</code> sage ich, dass an allen Seiten (oben, rechts, unten, links) des <code class="language-plaintext highlighter-rouge">Button</code> zusätzlich 2 Pixel Platz gelassen werden soll. Damit wird nicht der <code class="language-plaintext highlighter-rouge">Button</code> kleiner, sondern für die anderen Elemente im <code class="language-plaintext highlighter-rouge">Grid</code> steht weniger Platz zur Verfügung. Für die Optik bedeutet dies aber einen wesentlichen Gewinn.</p>
<p>Hier der <code class="language-plaintext highlighter-rouge">Button</code> im fertigen Layout <strong>ohne</strong> Margin:
<img src="https://www.lernmoment.de/images/wpf-youtube-player-okbutton-ohne-margin.png" alt="Ok-Button des WPF YouTube Players mit Margin" /></p>
<p>Diese letzteres Version ist für mich weniger attraktiv.</p>
<h3 id="alignment---position-eines-steuerelements-in-der-zelle">Alignment - Position eines Steuerelements in der Zelle</h3>
<p>Nun wollen wir uns noch um die Eigenschaften <code class="language-plaintext highlighter-rouge">VerticalAlignment</code> und <code class="language-plaintext highlighter-rouge">HorizontalAlignment</code> kümmern. Wie bei der <code class="language-plaintext highlighter-rouge">Margin</code> sind dies keine Eigenschaften die spezifisch für das <code class="language-plaintext highlighter-rouge">Grid</code> sind. Jedoch haben sie einen Einfluss auf das Layout im <code class="language-plaintext highlighter-rouge">Grid</code>.</p>
<p>Wie du an den beiden Bildern im vorherigen Kapitel sehen konntest nimmt die <code class="language-plaintext highlighter-rouge">TextBox</code> nicht die komplette Höhe der Zeile ein. Dabei habe ich kein <code class="language-plaintext highlighter-rouge">Margin</code> definiert:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!--Zeile 1--></span>
<span class="nt"><TextBox</span> <span class="na">x:Name=</span><span class="s">"YoutubeUrlTextBox"</span> <span class="na">VerticalAlignment=</span><span class="s">"Center"</span>
<span class="na">Grid.Row=</span><span class="s">"1"</span> <span class="na">Grid.Column=</span><span class="s">"1"</span> <span class="na">Grid.ColumnSpan=</span><span class="s">"3"</span><span class="nt">/></span>
</code></pre></div></div>
<p>Allerdings habe ich dort die Eigenschaft <code class="language-plaintext highlighter-rouge">VerticalAlignment</code> auf <code class="language-plaintext highlighter-rouge">Center</code> gesetzt. Für das <em>Alignment</em> (<em>Horizontal</em> wie auch <em>Vertical</em>) gibt es die folgenden Werte:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Bottom</code> - Das Steuerelement wird am unteren Rand der Zelle platziert und nimmt nach oben soviel Platz ein wie sein Inhalt benötigt.</li>
<li><code class="language-plaintext highlighter-rouge">Center</code> - Das Steuerelement wird mittig in der Zelle platziert und nimmer dort soviel Platz ein wie sein Inhalt benötigt.</li>
<li><code class="language-plaintext highlighter-rouge">Stretch</code> - Das Steuerelement nimmt die komplette Zelle ein (unabhängig von dem tatsächlich benötigten Platz). Dieses ist der <strong>Standardwert</strong>.</li>
<li><code class="language-plaintext highlighter-rouge">Top</code> - Das Steuerelement wird am oberen Rand platziert und nimmt nach unten soviel Platz ein wie sein Inhalt benötigt.</li>
</ul>
<p>Die Unterschiede kannst du anhand der <code class="language-plaintext highlighter-rouge">TextBox</code> sehr gut sehen. Wie hoch die <code class="language-plaintext highlighter-rouge">TextBox</code> ist, wird durch die Schriftgröße bestimmt. Verwendest du also wie in unserem Beispiel <code class="language-plaintext highlighter-rouge">VerticalAlignment="Center"</code>, dann bleiben in der Zelle oben und unten einige Pixel frei. Das liegt daran, dass in der Zelle mehr Platz in der Höhe ist (bedingt durch die Höhe des <code class="language-plaintext highlighter-rouge">okButton</code> der in der gleichen Zeile liegt), als die verwendete Schriftgröße benötigt. Würdest du beispielsweise die <code class="language-plaintext highlighter-rouge">FontSize</code> auf den Wert <code class="language-plaintext highlighter-rouge">20</code> setzen, dann würdest du sehen, dass die komplette Höhe der Zeile anwächst (weil für die Zeile <code class="language-plaintext highlighter-rouge">Height="Auto"</code> definiert ist) und das die <code class="language-plaintext highlighter-rouge">TextBox</code> wieder die ganze Höhe einnimmt.</p>
<p>Definierst du in diesem Beispiel nichts für <code class="language-plaintext highlighter-rouge">VerticalAlignment</code>, dann wird der Standardwert (<code class="language-plaintext highlighter-rouge">Stretch</code>) genommen. Somit wird zwar die <code class="language-plaintext highlighter-rouge">TextBox</code> in der kompletten Zelle angezeigt, aber ein enthaltener Text wird am oberen Rand gezeigt. Das sieht auch etwas komisch aus.</p>
<p><img src="https://www.lernmoment.de/images/wpf-youtube-player-text-bei-stretch.png" alt="TextBox WPF YouTube Players mit VerticalAlignment=Stretch" /></p>
<p><em>Hinweis:</em> Noch spannendere Effekte bekommst du bei der <code class="language-plaintext highlighter-rouge">TextBox</code>, wenn du die <code class="language-plaintext highlighter-rouge">HorizontalAlignment</code> auf einen anderen Wert als <code class="language-plaintext highlighter-rouge">Stretch</code> setzt. Dann ist die <code class="language-plaintext highlighter-rouge">TextBox</code> nämlich fast nicht mehr sichtbar, wenn kein Text enthalten ist. Das liegt daran, dass für die Bestimmung des Platzbedarfs in der Breite der Text relevant ist. Die <code class="language-plaintext highlighter-rouge">TextBox</code> wird zwar breiter, wenn du darin tippst, aber das ist eine Oberflächengestaltung, die du wahrscheinlich nicht haben möchtest. Möchtest du einfach den Text in der Mitte positionieren, dann kannst du die Eigenschaft <code class="language-plaintext highlighter-rouge">TextAlignment</code> verwenden. Dort gibt es den Wert <code class="language-plaintext highlighter-rouge">Center</code> mit dem der Text mittig (bezogen auf die Breite der <code class="language-plaintext highlighter-rouge">TextBox</code>) positioniert wird.</p>
<h3 id="steuerelemente-übereinander-platzieren">Steuerelemente übereinander platzieren</h3>
<p>Bisher haben wir die Steuerelemente entlang der <em>X</em>- und <em>Y</em>-Achse platziert. Das <code class="language-plaintext highlighter-rouge">Grid</code> bietet aber auch die Möglichkeit Steuerelemente übereinander, also quasi entlang der <em>Z</em>-Achse, zu positionieren. Ob es wirklich viele Anwendungsfälle gibt überlasse ich dir. Einen habe ich jedoch und den möchte ich dir hier vorstellen:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!--Zeeile 2--></span>
<span class="nt"><cef:ChromiumWebBrowser</span> <span class="na">x:Name=</span><span class="s">"YouTubePlayer"</span> <span class="na">Address=</span><span class="s">"https://www.youtube.com/channel/UC5jCUQ6IPHtQP5r4y9byCqA"</span>
<span class="na">Grid.Row=</span><span class="s">"2"</span> <span class="na">Grid.Column=</span><span class="s">"1"</span> <span class="na">Grid.ColumnSpan=</span><span class="s">"3"</span> <span class="na">Margin=</span><span class="s">"5,5,5,5"</span><span class="nt">/></span>
<span class="nt"><Label</span> <span class="na">x:Name=</span><span class="s">"HinweisLabel"</span> <span class="na">Grid.Row=</span><span class="s">"2"</span> <span class="na">Grid.Column=</span><span class="s">"0"</span> <span class="na">Grid.ColumnSpan=</span><span class="s">"5"</span> <span class="na">Content=</span><span class="s">"Hinweis: Ein Ersatz für die MessageBox"</span>
<span class="na">FontSize=</span><span class="s">"35"</span> <span class="na">FontWeight=</span><span class="s">"Bold"</span> <span class="na">HorizontalAlignment=</span><span class="s">"Center"</span> <span class="na">VerticalAlignment=</span><span class="s">"Center"</span>
<span class="na">Background=</span><span class="s">"#E5D5F3EB"</span> <span class="na">Visibility=</span><span class="s">"Hidden"</span><span class="nt">/></span>
</code></pre></div></div>
<p>Wie bisher auch ist das <code class="language-plaintext highlighter-rouge">ChormiumWebBrowser</code> Steuerelement zentral in Zeile 2 angesiedelt. Außerdem habe ich bisher Nachrichten an den Benutzer über eine <code class="language-plaintext highlighter-rouge">MessageBox</code> ausgegeben. Es gibt allerdings auch einen visuell ansprechenderen Weg. Den habe ich hier mit dem <code class="language-plaintext highlighter-rouge">HinweisLabel</code> umgesetzt.</p>
<p>Wenn du der gleichen Zelle (oder auch mehreren Zellen wie in diesem Fall) mehrere Steuerelemente zuweist, dann werden sie während dem Layout übereinander platziert. Dabei ist die Reihenfolge in der sie in der <em>XAML</em>-Datei stehen von Relevanz. Das Steuerelement welches zu erst in der Datei steht wird als unterstes angezeigt. In unserem Beispiel wird also erst der <em>Browser</em> und dann das <code class="language-plaintext highlighter-rouge">Label</code> angezeigt.</p>
<p>Um nun den Effekt zu bekommen, dass das <code class="language-plaintext highlighter-rouge">HinweisLabel</code> nur für einen Hinweis angezeigt wird, verwende ich die <code class="language-plaintext highlighter-rouge">Visibility</code> Eigenschaft. Diese steht erstmal auf <code class="language-plaintext highlighter-rouge">Hidden</code>, also versteckt, und wird bei Bedarf aus dem Quellcode heraus auf <code class="language-plaintext highlighter-rouge">Visible</code> und nach einigen Sekunden zurück auf <code class="language-plaintext highlighter-rouge">Hidden</code> gesetzt. Wie das genau geht, siehst du <a href="https://github.com/LernMoment/wpf-tutorial-deutsch/blob/1f08c0ed79f2f51e5dbbd336dfca693eb9b5f619/GridGrundlagen/MainWindow.xaml.cs#L37">hier im Quellcode</a>.</p>
<h3 id="zusätzliche-ressourcen">Zusätzliche Ressourcen</h3>
<p>Solltest du noch weiteren Klärungsbedarf zum <code class="language-plaintext highlighter-rouge">Grid</code> haben, dann kann ich dir diese Ressourcen empfehlen:</p>
<ul>
<li><a href="http://openbook.rheinwerk-verlag.de/visual_csharp_2012/1997_19_001.html#dodtp55f29b28-56fc-4781-943e-56e903b0bd27">Das Grid-Steuerelement - Openbook vom Rheinwerk Verlag</a></li>
<li><a href="https://docs.microsoft.com/de-de/dotnet/framework/wpf/controls/panels-overview">Übersicht über Panel-Elemente - Microsoft Docs</a></li>
<li><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.controls.grid?view=netcore-3.1">Die Grid Klasse - Microsoft Docs</a></li>
<li><a href="/lernmail-kurse/wpf-tictactoe-fuer-einsteiger/">WPF-Übungskurs für Einsteiger - LernMoment</a></li>
</ul>
<p>Ich hoffe dieser Artikel hat dir geholfen. Wenn du Fragen oder Rückmeldung dazu hast, dann <a href="mailto:jan@lernmoment.de">freue ich mich über eine Mail</a>.</p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/alle/wpf-grid-panel-xaml-grundlagen/">Grundlagen des WPF Grid-Panels in XAML</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 15, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/einfuehrung-code-snippets2020-03-02T18:13:09+01:002020-03-02T18:13:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Mit Codeausschnitten (bzw. Code-Snippets auf Englisch) bekommst du eine einfache Möglichkeit um dir einiges an Tipparbeit zu ersparen. <em>Visual Studio</em> hat für Elemente wie eine <code class="language-plaintext highlighter-rouge">foreach</code>-Schleife, <code class="language-plaintext highlighter-rouge">if</code>-Abfragen und vieles mehr bereits Codeausschnitte definiert. Wenn du diese verwendest, dann braquchst du nur 2-3 Buchstaben tippen, 2x die Tabulatortaste drücken und <em>Visual Studio</em> fügt automatisch einen Codeausschnitt ein. Bei der <code class="language-plaintext highlighter-rouge">if</code>-Abfrage bekommst du so z.B. die runden und geschweiften Klammern direkt in der passenden Formatierung eingefügt. Ein paar mehr Details dazu erkläre ich dir <a href="https://youtu.be/teb_83Vxou4?t=295">in diesem Video</a>.</p>
<p><a href="https://docs.microsoft.com/de-de/visualstudio/ide/code-snippets?view=vs-2019">Hier</a> gibt es ein paar Hintergrundinformationen zu Codeausschnitten von Microsoft und <a href="https://docs.microsoft.com/de-de/visualstudio/ide/visual-csharp-code-snippets?view=vs-2019">hier</a> sind alle “Standardcodeausschnitte” aufgelistet und kurz erklärt.</p>
<p>Zusätzlich haben sich jedoch schon viele Entwickler Gedanken gemacht welche weiteren <em>Codeausschnitte</em> noch hilfreich wären. So findest du mit etwas Suchen einige wirklich <strong>hilfreiche <em>Codeausschnitte</em> im Netz</strong>. Es gibt da z.B. <a href="https://www.benday.com/2019/06/20/code-snippets-for-visual-studio-visual-studio-code-and-visual-studio-for-mac/">diese Seite</a> oder auch <a href="http://www.visualstudiocodesnippets.com">diese Seite</a>.
<strong>WICHTIG:</strong> Wie mit allen Dingen die du aus dem Internet lädst solltest du schauen was du tatsächlich bekommst. Microsoft erklärt <a href="https://docs.microsoft.com/de-de/visualstudio/ide/best-practices-for-using-code-snippets?view=vs-2019#downloaded-code-snippets">hier</a> worauf du bei <em>Codeausschnitten</em> aus dem Internet achten solltest.</p>
<p>Wenn dir das alles nicht reicht, oder du gute Ideen für <strong><em>Codeausschnitte</em></strong> hast, dann kannst du auch <strong>selber welche erstellen</strong>. Deine eigenen <em>Codeausschnitte</em> kannst du entweder als einzelne Dateien speichern oder du kannst sogar deine eigene <em>Visual Studio Erweiterung</em> mit mehreren <em>Codeausschnitten</em> erstellen. In <a href="https://docs.microsoft.com/de-de/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2019">diesem Artikel</a> gibt es eine erste Einführung zu beiden Wegen. Ich werde dazu auch demnächst ein Video veröffentlichen. Solltest du also noch nicht den LernMoment-YouTube-Kanal abonniert haben, kannst du das <a href="https://www.youtube.com/channel/UC5jCUQ6IPHtQP5r4y9byCqA?sub_confirmation=1">hier</a> machen ;-).</p>
<p><em>Tipps für Fortgeschrittene:</em> <a href="https://docs.microsoft.com/de-de/visualstudio/ide/productivity-features?view=vs-2019"><em>Hier</em></a> <em>hat Microsoft einige weitere Produktivitätstipps für Visual Studio zusammengestellt.</em> <a href="https://entwickler.de/online/windowsdeveloper/visual-studio-text-editor-funktionen-254658.html"><em>Auf entwickler.de</em></a> <em>gibt es ebenfalls einen tollen Artikel mit teilweise etwas exotischeren Tipps.</em></p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/einfuehrung-code-snippets/">Code Snippets in Visual Studio 2019</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 02, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/wichtige-tastaturkuerzel-visual-studio2020-03-24 07:00:00 +0100T00:00:00-00:002020-03-02T16:13:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p><em>Visual Studio</em> ist DAS Werkzeug, welches du als Einsteiger auf deinem Weg zum C# Entwickler am meisten einsetzen wirst (hoffe ich ;). Daher solltest du fit darin werden <em>Visual Studio</em> möglichst effizient zu bedienen. Dazu gehört, dass du wenigstens einige der vielen Tastaturkürzel kennst und auch aktiv einsetzt. Sie helfen dir, sobald du einigermaßen fit bist mit der C# Syntax, wirklich produktiv zu arbeiten. Hier sind 5 Tastaturkürzel die ich häufig einsetze:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">F5</code> (Starten) - Alle Änderungen speichern, kompilieren und die Anwendung im Debugger starten</li>
<li><code class="language-plaintext highlighter-rouge">F12</code> (Gehe zu Definition) - Wenn der Cursor im Editor auf einem Element steht (z.B. einem Methodenaufruf) bringt dich <code class="language-plaintext highlighter-rouge">F12</code> direkt zur Definition dieses Elements (also im Beispiel zum Quellcode der entsprechenden Methode).</li>
<li><code class="language-plaintext highlighter-rouge">UMSCHALT</code>+<code class="language-plaintext highlighter-rouge">F12</code> (Alle Verweise suchen) - Wenn der Cursor im Editor auf einem Element steht (z.B. einer Methodendefinition) sucht <em>Visual Studio</em> alle Verweise und gibt sie dir in einem <em>…-Verweise</em> Fenster aus.</li>
<li><code class="language-plaintext highlighter-rouge">STRG</code>+<code class="language-plaintext highlighter-rouge">-</code> (Zurück) - Bist du mit <code class="language-plaintext highlighter-rouge">F12</code> an eine andere Stelle gesprungen, dann bringt dich diese Tastenkombination wieder an die vorherige Stelle zurück. Das geht übrigens nicht nur bei <code class="language-plaintext highlighter-rouge">F12</code> sondern ganz allgemein bei der Navigation im Editor.</li>
<li><code class="language-plaintext highlighter-rouge">STRG</code>+<code class="language-plaintext highlighter-rouge">.</code> (“Glühbirne ausführen”) - Steht der Cursor im Editor auf einem Hinweis der eine “Glühbirne” anzeigt (z.B. Ein Fehler der rot unterstrichen ist), kannst du mit dieser Tastenkombination den Dialog der “Glühbirne” öffnen und dann mit den Pfeiltasten darin navigieren. Dieses benutze ich häufig um beispielsweise <code class="language-plaintext highlighter-rouge">using</code> Anweisung aufzunehmen.</li>
<li>Bonus:
<ul>
<li><code class="language-plaintext highlighter-rouge">STRG</code> + <code class="language-plaintext highlighter-rouge">K</code> -> <code class="language-plaintext highlighter-rouge">C</code> (markierte Zeilen kommentieren) - Wenn du mehrere Zeilen in deinem Quellcode markierst, dann die <code class="language-plaintext highlighter-rouge">STRG</code> Taste drückst (und gedrückt hälst) und <em>nacheinander</em> die Taste <code class="language-plaintext highlighter-rouge">K</code> und <code class="language-plaintext highlighter-rouge">C</code> drückst, wird vor jeder Zeile die markiert ist das Kommentarzeichen (z.B. <code class="language-plaintext highlighter-rouge">//</code> für C# oder <code class="language-plaintext highlighter-rouge"><!-- --></code> für XAML) eingefügt.</li>
<li><code class="language-plaintext highlighter-rouge">STRG</code> + <code class="language-plaintext highlighter-rouge">K</code> -> <code class="language-plaintext highlighter-rouge">U</code> (Kommentarzeichen aus markierten Zeilen entfernen) - Macht die vorherige Aktion wieder rückgängig.</li>
</ul>
</li>
</ul>
<p><em>Hinweis: Einige dieser Tastaturkürzel und weitere Produktivitätstricks erkläre ich dir im Detail in</em> <a href="https://youtu.be/teb_83Vxou4"><em>diesem Video</em></a>.</p>
<p>Microsoft bietet <a href="https://docs.microsoft.com/de-de/visualstudio/ide/default-keyboard-shortcuts-in-visual-studio?view=vs-2019">hier</a> einen Überblick aller verfügbaren Tastaturkürzel. Leider wird dich als Einsteiger das selten wirklich weiter bringen. Daher solltest du in <em>Visual Studio</em> selber nach den Tastaturkürzeln ausschau halten (z.B. werden diese häufig in den Menüs / Kontext-Menüs angezeigt). Eine Suche im Web mit dem Namen der Funktionalität und der Phrase “Tastaturkürzel in Visual Studio 2019” sollte dich auch weiterbringen. Natürlich kannst du auch gerne <a href="mailto:jan@lernmoment.de">mir eine Frage dazu stellen</a>.</p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/wichtige-tastaturkuerzel-visual-studio/">Die 5 wichtigsten Tastaturkürzel in Visual Studio 2019 für Einsteiger</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 02, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/visual-studio-2019-ueberblick2020-03-02T13:13:09+01:002020-03-02T13:13:09+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Der erste Start von Visual Studio 2019 kann schon etwas irritierend sein. Nachdem du dich für eine von vielen Projektvorlagen entschieden hast, werden dir viele Fenster angezeigt die für dich vielleicht erstmal keinen Sinn machen.</p>
<p>Im folgenden erkläre ich dir als Einsteiger in Visual Studio und C# welches die wichtigsten Fenster sind und was sie bedeuten. Wenn du eher der visuelle Mensch bist oder mehr Details brauchst, dann kannst du dir auch mein <a href="https://youtu.be/xhD1HCVj5V0?t=1337">Visual Studio 2019 Tutorial auf YouTube</a> anschauen. Darin zeige ich dir die Fenster <del>am offenen Herzen</del> direkt in Visual Studio.</p>
<p>Hier ein Überblick über die Fenster und deren Funktionen die ich am wichtigsten finde:</p>
<ul>
<li><strong>Editor</strong> - Offensichtlich DAS wichtigste Fenster überhaupt. Hier gibst du deinen Quellcode ein. Dabei unterstützen dich Funktionen wie das <strong>Refactoring</strong> (vom einfach Umbenennen von Methoden bis hin zum automatischen Erstellen von Methoden aus markiertem Quellcode), die <strong>vertikale Scrolleiste (Bildlaufleiste)</strong> (zeigt dir Änderungen, Fehler, Breakpoints und sogar eine “Lupe” zur schnellen Navigation in der Datei) und <strong>CodeLens / Tastaturkürzel zur Navigation</strong>. Einen Überblick über diese und weitere Funktionen vom Editor findest du in <a href="https://docs.microsoft.com/de-de/visualstudio/ide/writing-code-in-the-code-and-text-editor?view=vs-2019">diesem Artikel von Microsoft</a>.</li>
<li><strong>Eigenschaftenfenster</strong> - Dieses ist insbesondere dann relevant, wenn du eine Oberfläche z.B. mit WPF oder WinForms erstellst. Dann hilft es dir einen ersten <strong>Überblick zu Eigenschaften und Events</strong> zu bekommen (siehe dazu mein aktuelles <a href="https://www.youtube.com/playlist?list=PLP2TrPpx5VNk2g07AKxyIGdsUJNA95CDt">Einstieg in WPF Tutorial</a>). Aber auch bei anderen Projekten nutze ich gerne die Möglichkeit mir den <strong>Pfad einer Datei</strong> anzusehen oder zu bestimmen ob eine <strong>Datei ins Ausgabeverzeichnis kopiert</strong> werden soll (siehe dazu das Video <a href="https://youtu.be/874NuVyFg7I">Text-/XML-Datei in VisualStudio einbinden</a>).</li>
<li><strong>Projektmappenexplorer</strong> - Dieses Fenster nutze ich neben dem Editor am meisten. Mir gibt es einen guten <strong>Überblick über die Projektstruktur</strong> (ein wichtiger Bestandteil der Softwarearchitektur), hier ist für mich der Einsprungpunkt zur Verwaltung von externen Bibliotheken via NuGet (siehe <a href="https://www.lernmoment.de/alle/warum-nuget/">dieser Artikel (inkl. Video)</a> für Details) und ich lasse mir von hier häufig den Änderungsverlauf einer Datei anzeigen.</li>
<li><strong>Fehlerliste</strong> - Die Fehlerliste ist eines der Hauptausgabefenster des Compilers (hier ein wirklich <a href="https://www.imenja.io/die-microsoft-net-compiler-platform-roslyn-teil-1-grundlagen/">super Artikel</a> der dir einige Details zum Compiler erklärt). Ich nutze die Fehlerliste wenn ich mit einer Fehlermeldung nichts anfangen kann. Es gibt zu jedem Fehler den Link <strong>Hilfe anzeigen</strong>. Damit wird ein Browser geöffnet und die Suche gestartet direkt mit der Fehlermeldung. Weiterhin gibt es die Möglichkeit einen <strong>Doppelklick auf einen Fehler</strong> zu machen und so direkt an die passenden Stelle im Editor zukommen. Auch die Anzeige der Warnungen ist für mich immer relevant, weil ich versuche möglichst keine <strong>Warnungen vom Compiler</strong> zu haben. Denn obwohl die Anwendung trotzdem ausgeführt werden kann, ist jede Warnung eine potentielle Gefahrenquelle.</li>
<li><strong>Ausgabefenster</strong> - Das Fenster in dem du sehen kannst wie die verschiedenen Tools (z.B. Compiler) aufgerufen werden. Ich benutze dieses Fenster aber auch teilweise zur Laufzeit. Denn hier findest du die <strong>Ausgabe von <code class="language-plaintext highlighter-rouge">Debug.Writeline</code></strong>. Grundsätzlich empfehle ich die Verwendung eines “ordentlichen” Logs und natürlich des Debuggers, aber manchmal ist es wirklich hilfreich, wenn ich einfach mal kurz im Quellcode zur Laufzeit eine Ausgabe machen kann. Neben dieser Ausgabe findest du hier auch die <strong>Ausgabe von <code class="language-plaintext highlighter-rouge">Git</code></strong>. Immer wenn du eine Aktion in der Quellcodeverwaltung über den Team-Explorer machst, wird “unter der Haube” <code class="language-plaintext highlighter-rouge">git</code> auf der Kommandozeile ausgeführt. Wenn es da mal zu Problemen kommt (was durchaus passiert), schaue ich immer zuerst in der Ausgabe ob ich weitere Hinweise finde.</li>
<li><strong>Git-Änderungen & Git-Repository</strong> - Die Fenster für Aufgaben rund um die Quellcodeverwaltung. Ich benutze hier besonders intensiv die Möglichkeit <strong>zwischen Branches zu wechseln</strong> (dazu gibt es bald das <em>ultimative Git / GitHub mit Visual Studio 2019 Tutorial</em>), die aktuellen <strong>Änderungen zu commiten</strong> und natürlich mein lokales <strong>Verzeichnis mit GitHub zu synchronisieren</strong>.</li>
</ul>
<p>Du hast Fragen zu Visual Studio die ich dir hier nicht beantwortet habe? Dann <a href="mailto:jan@lernmoment.de">schicke mir diese Frage per Mail</a> oder stelle sie der kompletten LernMoment Community am <a href="https://github.com/LernMoment/community-fragen/issues/new">Community-Fragen GitHub Projekt</a>.</p>
<p>Viel Spaß auf deinem Weg vom Einsteiger zum C# Entwickler</p>
<p>Jan von LernMoment.de</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/visual-studio-2019-ueberblick/">Die wichtigsten Fenster in Visual Studio 2019 kennenlernen</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am March 02, 2020.</p>
https://www.lernmoment.de/alle/git-mit-visual-studio-20192021-03-10 06:00:00 +0100T00:00:00-00:002020-02-14T06:00:00+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<blockquote>
<p><strong>WICHTIG:</strong> Aufgrund einer neuen Oberfläche für die Bedienung von Git in Visual Studio 2019 (ab Version 16.8) ist dieser Artikel nur für ältere Versionen von Visual Studio 2019 relevant. Eine Aktualisierung dieses Artikels folgt demnächst. Das einfache Klonen eines Projektes mit der neuen Oberfläche habe ich bereits <a href="/alle/projekt-klonen-von-github/">hier</a> beschrieben.</p>
</blockquote>
<p><em>Git</em> ist DIE dezentrale Versionsverwaltung. Cool 😎! Aber was soll das sein und wofür ist das überhaupt gut? Das erkläre ich dir in diesem Artikel.</p>
<p>Dezentrale Versionsverwaltung bedeutet, dass es nicht einen zentralen Server gibt den du für alle Aktionen mit der Versionsverwaltung benötigst. D.h. <em>git</em> kannst du, wenn du möchtest, ganz alleine für dich auf deinem Rechner verwenden. Vielleicht hast du schon mal eine “gute” Version deines Quellcodes komplett kopiert (also alle Dateien die dazugehören im Datei-Explorer in ein Verzeichnis mit dem Namen <em>MeineAnwendung_GuteVersion</em> oder <em>MeineAnwendung_v2</em> kopiert) um diese Version nicht zu verlieren. Um dieses Problem auf eine elegantere Weise zu lösen verwendest du ab jetzt am besten <em>git</em>.</p>
<p>Neben dem lokalen Sichern von Versionen bietet dir <em>git</em> aber auch die Möglichkeit deinen Quellcode auf einem Server zusichern. Das kannst du machen als Backup oder insbesondere auch, wenn du mit anderen Entwicklern zusammen an einem Projekt arbeiten möchtest. Wenn du dein Projekt auf einen Server schieben möchtest, dann kannst du z.B. <em>GitHub</em> verwenden. Im <a href="https://www.youtube.com/playlist?list=PLP2TrPpx5VNlLOYo5pook-0_0Uy0YLdHW">GitHub Tutorial Deutsch</a> zeige ich dir das ausführlich und in <a href="https://www.youtube.com/watch?v=V_IDzTNA_ns&list=PLP2TrPpx5VNlLOYo5pook-0_0Uy0YLdHW">GitHub ist nicht Git</a> erkläre ich den genauen Unterschied zwischen <em>Git</em> und <em>GitHub</em>.</p>
<p>Mit <em>Git</em> kannst du Änderungen an deinem Quellcode mit einem Zeitstempel und einer Beschreibung speichern. Der passende Fachbegriff dafür ist <em>einen Commit erstellen</em>. Hast du nun mehrere <em>Commits</em> erstellt, kannst du dir die Historie anschauen und auch auf den Stand eines ganz spezifischen <em>Commits</em> aus der Vergangenheit zurückfallen. Dank <em>Git</em> kannst du das alles lokal auf deinem Rechner machen ohne irgendetwas zusätzliches zu installieren (außer Visual Studio ;). Möchtest du dann später doch dein Projekt öffentlich verfügbar machen, kannst du immer noch deine lokalen Änderungen mit <em>GitHub</em> synchronisieren.</p>
<p>In dieser Kurzanleitung zeige ich dir die wichtigsten Schritte um mit <em>Visual Studio</em> und <em>Git</em></p>
<ol>
<li>ein Projekt zu erstellen / initialisieren,</li>
<li>einen Commit aus deinen Änderungen zu erstellen,</li>
<li>den aktuellen Verlauf deiner Commits anzuschauen und</li>
<li>auf einen älteren Commit zurück zufallen.</li>
</ol>
<div class="subscribe-notice">
<h5>Lerne GitHub mit Visual Studio zu verwenden!</h5>
<a href="https://www.udemy.com/github-fuer-entwickler/?referralCode=D2FD5CBAC0A15B17A09E" class="notice-button">Zum Online-Kurs "Einstieg in GitHub" >></a>
</div>
<h2 id="ein-projekt-erstellen">Ein Projekt erstellen</h2>
<p>Jedesmal, wenn du ein <em>neues Projekt</em> erstell hast, kannst du über die <em>Auswahlbox:</em> <code class="language-plaintext highlighter-rouge">Zur Quellcodeverwaltung hinzufügen</code> (unten rechts in der Status-Bar von Visual Studio) <em>Git</em> auswählen. Wählst du diese Option, was du eigentlich immer machen solltest ;-), wird automatisch im obersten Verzeichnis deines Projektes ein Ordner mit dem Namen <code class="language-plaintext highlighter-rouge">.git</code> angelegt. Darin werden sämtliche Informationen von <em>Git</em> gespeichert.</p>
<p><img src="https://www.lernmoment.de/images/git-mit-vs2019/zur-quellcodeverwaltung-hinzufuegen.jpg" alt="Zur Quellcodeverwaltung hinzufügen" /></p>
<p>Zusätzlich zum <code class="language-plaintext highlighter-rouge">.git</code> Verzeichnis werden auch gleich 2 <em>Commits</em> erstellt. Damit sind dann bereits alle zum Projekt gehörenden Dateien zur Versionsverwaltung hinzugefügt. Dieses wird dir im <code class="language-plaintext highlighter-rouge">Projektmappen-Explorer</code> in <em>Visual Studio</em> angezeigt. Dort siehst du vor den Dateien (z.B. <code class="language-plaintext highlighter-rouge">App.config</code>) ein Symbol welches aussieht wie ein Vorhängeschloss. Damit wird dir angezeigt, dass alle Änderungen in <em>Git</em> gespeichert sind.</p>
<p>Sobald du in einer Datei eine Änderung vornimmst, ändert sich das Symbol und zeigt einen <em>roten Haken</em> an. Dieser sagt dir, dass es Änderungen in der Datei gibt, für die bisher noch kein <em>Commit in Git</em> erstellt wurde.</p>
<p><strong>Die wichtigsten Schritte:</strong></p>
<p>1) Projekt erstellen mit:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Datei -> Neu -> Projekt...
</code></pre></div></div>
<p>oder über den Projekterstellungs-Assistent beim Start von Visual Studio.</p>
<p>2) Git aktivieren durch auswählen von</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Zur Quellcodeverwaltung hinzufügen -> Git
</code></pre></div></div>
<h2 id="einen-commit-erstellen">Einen Commit erstellen</h2>
<p>Nachdem du nun dein Projekt von <em>Git</em> verwalten lässt, solltest du deine Änderungen von Zeit zu Zeit mit einem <em>Commit</em> bei <em>Git</em> “abliefern”. <em>Git</em> sind alle deine Änderungen bekannt, aber es weiß nicht was deine Änderungen für dich bedeuten.</p>
<p>Hast du mehrere Dateien geändert, dann weiß <em>Git</em> auch nicht welche Änderungen für dich einen logischen Zusammenhang haben. Du könntest beispielsweise mehrere Änderungen gemacht haben, die dein Projekt um verschiedene Funktionalitäten erweitern. Ich versuche immer möglichst kleine <em>Commits</em> zu machen. Das bedeutet, dass ich nach wenigen Änderungen bereits ein Commit erstelle. Bevor ich hier jedoch wieder abschweife, zurück zur eigentlichen Anleitung (eine genauere Beschreibung der “best practices” für einen Commit bekommst du dann in einem späteren Artikel).</p>
<p>Der einfachste Weg alle deine aktuellen Änderungen in einen Commit zu packen ist, dass du in den <code class="language-plaintext highlighter-rouge">Team Explorer</code> gehst und dort den Bereich <code class="language-plaintext highlighter-rouge">Änderungen</code> auswählst. Dieser wird dir üblicherweise direkt angezeigt. Sollte das nicht der Fall sein, dann kannst du über das Haussymbol (<code class="language-plaintext highlighter-rouge">Startseite</code>) eine Übersichtsseite aufrufen und dort <code class="language-plaintext highlighter-rouge">Änderungen</code> auswählen.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/git-mit-vs2019/aenderungen-dialog.jpg" alt="Änderungen-Seite im Team-Explorer" /></p>
<p>Unterhalb vom gelben Textfeld siehst du alle aktuellen Änderungen aufgelistet. Diese Auflistung umfasst alle Dateien, die du seit dem letzten <em>Commit</em> geändert hast. Wenn du nun einfach eine Beschreibung für diese Änderung(en) in das gelbe Textfeld eingibst und den Button <code class="language-plaintext highlighter-rouge">Commit für alle</code> betätigst, hast du einen Commit erstellt. Damit verschwindet die Auflistung der Änderungen, weil diese ja nun in einem <em>Commit</em> beschrieben sind.</p>
<p>Diesen Prozess solltest du zukünftig kontinuierlich wiederholen. Damit kannst du dann im nächsten Schritt sehen welche Änderungen du wann und warum gemacht hast.</p>
<p><strong>Die wichtigsten Schritte:</strong></p>
<p>Im <code class="language-plaintext highlighter-rouge">Team Explorer</code>:</p>
<ol>
<li>Commit-Beschreibung eingeben</li>
<li><code class="language-plaintext highlighter-rouge">Commit für alle</code> Button betätigen</li>
</ol>
<h2 id="aktuellen-verlauf-anzeigen">Aktuellen Verlauf anzeigen</h2>
<p>Sobald du einige <em>Commits</em> erstellt hast, kannst du dir in <em>Visual Studio</em> den bisherigen Verlauf anschauen. Dazu gehst du am besten in den <code class="language-plaintext highlighter-rouge">Projektmappen-Explorer</code>. Darin kannst du auf der Datei für die du den Verlauf sehen möchtest das Kontextmenü (rechte Maustaste) öffnen und <code class="language-plaintext highlighter-rouge">Verlauf anzeigen...</code> auswählen. Dies öffnet einen weiteren Tab.</p>
<p>Darin siehst du für jeden <em>Commit</em> sowohl das Datum und auch die Nachricht. Wenn du zu einem <em>Commit</em> die Details sehen möchtest, dann gehst du auf diesen <em>Commit</em> im <em>Verlauf</em> und rufst über das <em>Kontextmenü</em> den Punkt <code class="language-plaintext highlighter-rouge">Commitdetails anzeigen</code> auf. Damit wechselt <em>Visual Studio</em> automatisch vom <code class="language-plaintext highlighter-rouge">Projektmappen-Explorer</code> zum <code class="language-plaintext highlighter-rouge">Team Explorer</code>. Darin siehst du auch welche Dateien vom <em>Commit</em> verändert wurden.</p>
<p>Insbesondere im Verlauf siehst du warum gute <em>Commit-Beschreibungen</em> wichtig sind. Sobald du nämlich einige <em>Commits</em> gemacht hast, wird es immer schwieriger einzelne <em>Commits</em> wiederzufinden. Insbesondere wenn einige Tage oder gar Wochen vergangen sind, dann kommst du mit kryptischen Beschreibungen nicht wirklich weiter.</p>
<p>Möchtest du den Verlauf für das ganze Projekt sehen, dann musst du den <code class="language-plaintext highlighter-rouge">Team Explorer</code> bemühen. Darin gehst du am besten über das Haussymbol zur <code class="language-plaintext highlighter-rouge">Startseite</code>. Dort wählst du dann <code class="language-plaintext highlighter-rouge">Branches</code> aus. Üblicherweise siehst du in der folgenden Auflistung nur den Projektnamen und dadrunter den Eintrag <code class="language-plaintext highlighter-rouge">master</code>. Solltest du mehrere <em>Branches</em> haben, dann wird dir der Aktive mit fettgedruckten Buchstaben angezeigt.</p>
<div class="subscribe-notice">
<h5>Du kennst dich noch nicht mit Visual Studio aus?</h5>
<a href="/einstieg-csharp/" class="notice-button">Hier geht's zum Online-Kurs "Einstieg in C#" >></a>
</div>
<p>Auf dem gewünschten Branch kannst du im <em>Kontextmenü</em> ebenfalls <code class="language-plaintext highlighter-rouge">Verlauf anzeigen...</code> auswählen. Dann siehst du alle Commits die es bisher in dem ausgewählten Branch gegeben hat.</p>
<p>Solltest du das Thema <em>Branches</em> noch nicht kennen ist das kein Problem. Verwende einfach erstmal <code class="language-plaintext highlighter-rouge">master</code>.</p>
<p><strong>Die wichtigsten Schritte:</strong></p>
<p>Im <code class="language-plaintext highlighter-rouge">Projektmappen-Explorer:</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Via Kontextmenü "Verlauf anzeigen..." auf der gewünschten Datei ausführen
</code></pre></div></div>
<h2 id="eine-ältere-version-commit-verwenden">Eine ältere Version (Commit) verwenden</h2>
<p>Gerade wenn es darum geht auf eine ältere Version zurück zu gehen gibt es bei <em>Git</em> ein paar Herausforderungen zu meistern. Wenn du im <em>Verlauf</em> (siehe vorherigen Abschnitt) einen <em>Commit</em> auswählst und dir das Kontextmenü anzeigen lässt, dann findest du den Eintrag <code class="language-plaintext highlighter-rouge">Zurücksetzen</code>.</p>
<p>Dieser Eintrag setzt jedoch nicht dein ganzes Projekt auf den Stand des <em>Commits</em> zurück, sondern macht genau diesen einen <em>Commit</em> rückgängig. Hast du beispielsweise im letzten Commit einen Fehler gemacht, dann kannst du ihn auf diese Weise rückgängig machen.</p>
<p>Ich würde dir erstmal davon abraten das <code class="language-plaintext highlighter-rouge">Zurücksetzen</code> in einem anderen Kontext auszuführen. Es macht dir zwar nichts kaputt, weil das <code class="language-plaintext highlighter-rouge">Zurücksetzen</code> als ein weiterer <em>Commit</em> im <em>Verlauf</em> auftaucht, aber es wird dann unübersichtlich und kompliziert.</p>
<p>Eine Alternative bekommst du mit der Funktionalität <code class="language-plaintext highlighter-rouge">Neuer Branch...</code>. Diese kannst du ebenfalls aus dem Kontextmenü eines <em>Commits</em> im <em>Verlauf</em> aufrufen. Wenn du diese Funktionalität verwendest, erstellst du einen neuen Zweig in <em>Git</em>. Das bedeutet, dass alle bisherigen Änderungen erhalten bleiben und du unabhängig davon eine andere Lösung ausprobieren kannst.</p>
<p>Bevor du einen neuen <em>Branch</em> erstellen kannst, musst du alle noch ausstehenden Änderungen per <em>Commit</em> abgeben. Wenn es noch Änderungen gibt, dann kannst du keinen neuen <em>Branch</em> erstellen.</p>
<p>Willst du also dein Projekt ab einer gewissen Stelle im <em>Verlauf</em> verändern, dann gehst du auf den entsprechenden <em>Commit</em>, wählst <code class="language-plaintext highlighter-rouge">Neuer Branch...</code> aus dem Kontextmenü und gibst im <code class="language-plaintext highlighter-rouge">Team Explorer</code> einen Namen für deinen Branch ein. Dies könnte zum Beispiel sein <em>“Lösungsweg2”</em>. Es ist bereits <code class="language-plaintext highlighter-rouge">Branch auschecken</code> ausgewählt und dies solltest du auch belassen. Nun einfach den Button <code class="language-plaintext highlighter-rouge">Branch erstellen</code> betätigen und du hast einen neuen Branch mit dem Projektstand zum ausgewählten <em>Commit</em> erstellt. In diesem Branch kannst du Änderungen machen und beliebig viele <em>Commits</em> erstellen.</p>
<p>Hast du nun in deinem neuen Branch deine Lösung soweit entwickelt wie nötig, kannst du diesen Branch zurück führen in deinen Ausgangsbranch (das wird <em>Merge</em> genannt). Somit hast du nicht mehr zwei parallele Zweige an denen entwickelt werden kann.</p>
<p>Nachdem du alle Änderungen in deinem Branch per <em>Commit</em> abgegeben hast, kannst du zurück in den <code class="language-plaintext highlighter-rouge">master</code> Branch wecheseln. Das machst du im <code class="language-plaintext highlighter-rouge">Team Explorer</code> im Bereich <code class="language-plaintext highlighter-rouge">Branches</code>. Dort siehst du, dass der von dir erstellte Branch momentan fettgedruckt ist. D.h. er ist momentan aktiv. Mache nun einen Doppelklick auf den Branch <code class="language-plaintext highlighter-rouge">master</code> direkt im <code class="language-plaintext highlighter-rouge">Team Explorer</code>. Damit wird dieser aktiv gesetzt.</p>
<p>Wenn nun der <code class="language-plaintext highlighter-rouge">master</code> Branch aktiv ist, kannst du auf ihm im <code class="language-plaintext highlighter-rouge">Team Explorer</code> per Kontextmenü die Funktion <code class="language-plaintext highlighter-rouge">Mergen aus...</code> auswählen. Damit öffnet sich eine neue Eingabe im <code class="language-plaintext highlighter-rouge">Team Explorer</code> bei der du deinen Branch im Bereich <code class="language-plaintext highlighter-rouge">Mergen aus Branch:</code> auswählen kannst. Die restlichen Einstellungen können so bleiben und du führst mit einem Klick auf den Button <code class="language-plaintext highlighter-rouge">Merge</code> den Vorgang aus.</p>
<p>Nun kann es passieren, dass du noch <em>Konflikte</em> auflösen musst. Dabei solltest du dir alles im Detail anschauen, aber üblicherweise kannst du immer die Änderungen aus der <code class="language-plaintext highlighter-rouge">Quelle</code> übernehmen.</p>
<p>Hoffentlich hat dir diese Anleitung ein wenig geholfen beim Umgang mit Git und Visual Studio.</p>
<p>Viel Erfolg beim Verwalten deiner Versionen mit Git und Visual Studio</p>
<p>Jan</p>
<p><a href="https://www.lernmoment.de/alle/git-mit-visual-studio-2019/">Versionskontrolle mit Git und Visual Studio 2019</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am February 14, 2020.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/erste-schritte-visual-studio-20192019-09-17T07:00:00+02:002019-09-17T07:00:00+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<blockquote>
<p>Schau dir auch die weiteren Folgen des <a href="/csharp-tutorial-deutsch/">C# Tutorial Deutsch</a> an.</p>
</blockquote>
<p>Die ersten Schritte in Visual Studio können ganz schön kompliziert sein. In diesem Tutorial zeige ich dir Schritt für Schritt was du tun musst um deine erste C#-Anwendung mit <strong>Visual Studio 2019</strong> Community Edition zu erstellen. Dabei starten wir mit der Installation und hören auf mit einer fertigen (kleinen) Anwendung.</p>
<p><em>Hinweis:</em> Da das Video etwas lang geworden ist, kannst du direkt zu den einzelnen Teilen springen. Die entsprechenden Links sind in der <a href="https://www.youtube.com/watch?v=xhD1HCVj5V0&list=PLP2TrPpx5VNkv4w1XbappnU0bfEwF_j-5">Videobeschreibung auf YouTube</a> verfügbar.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLP2TrPpx5VNkv4w1XbappnU0bfEwF_j-5" frameborder="0" allow="encrypted-media" allowfullscreen=""></iframe>
<p>Egal ob du in deinem Beruf weiterkommen möchtest, im Studium mit den Informatikvorlesungen nicht zurecht kommst oder einfach für dich Programmieren lernen möchtest, in diesem kostenlosen C# Tutorial in Deutsch erfährst du alles, was du brauchst um deine erste (kleine) Anwendung zu erstellen.</p>
<p>Schritt für Schritt zeige ich dir wie du Visual Studio 2019 in der Community Edition installierst, damit dein erstes Projekt erstellst, was Quellcode ist, wie du Quellcode in C# schreibst, wie Quellcode kompiliert wird, was kompilieren überhaupt bedeutet und wie du deine eigene Anwendung in der Konsole ausführst.</p>
<div class="subscribe-notice">
<h5>Lerne alles über C# und professionelle Softwareentwicklung</h5>
<a href="https://www.udemy.com/course/einstieg-in-csharp-software-programmieren-wie-ein-profi/?couponCode=CS_20-0921_LMDE" class="notice-button">Hier geht's zum Online-Kurs "Einstieg in C#" >></a>
</div>
<h3 id="weitere-links">Weitere Links</h3>
<ul>
<li><a href="https://www.visualstudio.com/de">Visual Studio 2019</a> - kostenlose Community Edition.</li>
<li><a href="https://docs.microsoft.com/de-de/visualstudio/install/install-visual-studio">Offizielle Installationsanleitung</a> - hier hat Microsoft im Detail beschrieben was du bei der Installation machen und beachten sollst. Habe ich dir im Video aber soweit alles erklärt.</li>
<li><a href="https://docs.microsoft.com/de-de/visualstudio/ide/whats-new-visual-studio-2019?view=vs-2019">Neues in Visual Studio 2019</a> - Artikel von Microsoft, der die wichtigsten Funktionalitäten in der aktuellen Version beschreibt.</li>
<li><a href="https://docs.microsoft.com/de-de/visualstudio/install/create-an-offline-installation-of-visual-studio?view=vs-2019">Offline Installation</a> - beschreibt wie die benötigten Komponenten von Visual Studio 2019 runtergeladen werden können und dann vorbereitet werden um sie auf einem Rechner ohne Internetverbindung zu installieren. Diesen Artikel gab es auch in Deutsch, aber momentan ist er nur auf Englisch verfügbar.</li>
<li><a href="https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/index">C# Sprachreferenz</a> Als solches ist die C# SPrachreferenz für den Einstieg sicherlich nicht geeignet, ABER um z.B. alle Schlüsselwörter zu sehen und eine gute Erklärung zubekommen was damit gemeint ist, finde ich die Seiten schon gut.</li>
</ul>
<h3 id="der-komplette-quellcode-für-diese-folge">Der komplette Quellcode für diese Folge:</h3>
<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">HelloWorld</span>
<span class="p">{</span>
<span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Hallo Welt"</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Anwendung wird beendet durch drücken von 'Enter'!"</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Viel Erfolg für deine C# Anwendung</p>
<p>Jan</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/erste-schritte-visual-studio-2019/">UPDATE: C# Tutorial Deutsch - Erste Schritte (VisualStudio 2019)</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am September 17, 2019.</p>
https://www.lernmoment.de/alle/visual-studio-2019-tutorial-verfügbar2019-09-17T02:00:00+02:002019-09-17T02:00:00+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<p>Bereits Anfang 2016 habe ich im Rahmen meines <a href="/csharp-tutorial-deutsch/">C# Tutorials Deutsch</a> eine erste Einführung in Visual Studio gegeben. Visual Studio 2019 ist zwar schon seit einiger Zeit erschienen, aber ich habe mich mit einem großartigen Video-Team (Danke Michael & Ben) zusammen getan und nun eine Neuauflage des Videos erstellt.</p>
<p>Dabei ist nicht nur die Videoqualität nochmals wesentlich verbessert worden (Danke Michael & Ben), sondern ich habe auch inhaltlich nochmals vieles ergänzt. Das komplette Video zu Visual Studio 2019 findest du <a href="/csharp-tutorial-deutsch/erste-schritte-visual-studio-2019/">hier</a>.</p>
<figure>
<a href="/csharp-tutorial-deutsch/erste-schritte-visual-studio-2019/" target="_blank"><img src="/images/VS2019-Erste-Schritte.jpg" alt="image" /></a>
</figure>
<p>Viel Spaß beim anschauen!</p>
<p><a href="https://www.lernmoment.de/alle/visual-studio-2019-tutorial-verfu%CC%88gbar/">NEU - Erste Schritte mit C# und Visual Studio 2019</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am September 17, 2019.</p>
https://www.lernmoment.de/alle/was-bedeutet-debuggen2018-05-02T02:00:00+02:002018-05-02T02:00:00+02:00Daniel Gustorffhttps://www.lernmoment.dedaniel@lernmoment.de
<blockquote>
<p>Debuggen beschreibt in der Softwareentwicklung den Prozess der Fehlersuche.</p>
</blockquote>
<p>Das Wort Debuggen kommt daher, dass es in der Frühzeit der Computer immer wieder vor gekommen ist, dass Käfer oder andere Kleintiere in den Computern herumgekrochen sind und dort zu Kurzschlüssen und damit Fehlverhalten geführt haben. Damals wurden zum Durchführen der Rechenoperationen Relais verwendet, die durch Tiere zusätzlich blockiert werden konnten. Es kam also zu Fehlern im Programmablauf durch Käfer (englisch Bugs). Um diese Fehler zu beseitigen, mussten die Tiere aus dem Gerät entfernt werden. Der Computer musste also Entkäfert (debugged) werden. Diese Bezeichnung hat sich bis heute für die Fehlersuche gehalten, auch wenn heute in der Regel keine Tiere mehr für die Fehler verantwortlich sind.</p>
<p>Wenn heute niemand mehr mit Lampen durch Computer krabbeln muss, was passiert dann, wenn es um Fehlerbeseitigung geht?</p>
<p>Es gibt grob 2 Arten von Fehlern, die in der Softwareentwicklung vorkommen können.</p>
<h3 id="syntaxfehler">Syntaxfehler</h3>
<p>Bereits während der Entwicklung können Syntaxfehler auftreten. Diese Fehler führen dazu, dass der Code nicht kompiliert werden kann. Die meisten Entwicklungsumgebungen zeigen diese beim Kompilieren oder bereits während der Codeerstellung an. Dadurch ist es häufig nicht sehr aufwändig diese Fehler zu finden. VisualStudio unterstreicht fehlerhafte Eingaben zum Beispiel, um den Entwickler darauf hin zu weisen, dass hier ein Fehler vorliegt.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/was-bedeutet-debuggen/syntaxfehler-code.png" alt="Syntaxfehler im Quellcode" /></p>
<p>Hier fehlt das Semikolon am Ende der Zeile. Wenn man nun versucht den Code auszuführen, wird in der Fehlerliste ein Hinweis gegeben, dass ein Fehler vorliegt und um was für eine Art Fehler es sich handelt.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/was-bedeutet-debuggen/syntaxfehler-visualstudio.png" alt="Syntaxfehler iin Visual Studio" /></p>
<p>Durch diese Fehlermeldung ist es sehr einfach den Fehler zu beheben. Leider sind nicht alle Fehlermeldungen so eindeutig. Wodurch es auch beim Beheben von Syntaxfehlern die eine oder andere Schwierigkeit geben kann. Es gibt jedoch im Umfeld von VisualStudio auch die Möglichkeit eine Hilfe zu den Fehlermeldungen auf zu rufen, die bei der Behebung helfen können.</p>
<h3 id="laufzeitfehler">Laufzeitfehler</h3>
<p>Eine andere Fehlerart sind Laufzeitfehler. Wie der Name bereits sagt, treten diese Fehler erst zur Laufzeit auf. Hier kann man wiederum zwischen zwei Arten unterscheiden. Logische Fehler, das heißt das Programm tut nicht das, was man erwartet. Außerdem gibt Laufzeitfehler, die zum Absturz des Programms oder Endlosschleifen (Deadlock) während der Ausführung führen. Laufzeitfehler, die dazu führen, dass ein Programm nicht mehr Funktioniert, sind mit VisualStudio verhältnismäßig einfach zu entdecken. Hier hilft das Werkzeug mit. Kommt das Programm an eine Stelle, an der zum Beispiel durch 0 geteilt werden soll (das Ergebnis wäre unendlich, es lässt sich durch einen Computer jedoch nicht berechnen, so entsteht ein Ausnahmefehler, der bei der Ausführung angezeigt wird.</p>
<p><img src="https://www.lernmoment.de/images/was-bedeutet-debuggen/divide-by-zero-exception.png" alt="Divide by zero exception" /></p>
<p>Fehler die ähnlich geartet sind, führen in der Regel zu solchen Ausnahmefehlern. Wenn man sein Programm aus der Entwicklungsumgebung startet, kann man sie sehr einfach erkennen und hoffentlich auch entsprechend schnell beseitigen. Klassische Fehler diese Art sind z.B. StackOverflow Fehler, hierbei wir eine Funktion immer wieder aufgerufen, oft z.B. weil man eine Funktion beim Verändern eines Parameters aufruft und darin wieder auf den Parameter zugreift. Immer wieder treten auch NullReferenz Fehler auf. In diesem Fall versucht man auf eine Instanz eines Objekts (oder Methoden bzw. Eigenschaften davon) zuzugreifen, welche noch gar nicht erstellt wurde.</p>
<p>Die andere Kategorie von Laufzeitfehlern sind logische Fehler. Diese zu erkennen und zu finden ist deutlich schwieriger. Ein Beispiel für einen logischen Fehler ist das nicht einhalten von Punkt-vor-Strich Rechnung bei der Berechnung von Zahlen.</p>
<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">=</span><span class="m">3</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">j</span><span class="p">=</span><span class="m">4</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">k</span><span class="p">=</span><span class="m">5</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">ergebnis</span> <span class="p">=</span> <span class="n">i</span> <span class="p">+</span> <span class="n">j</span> <span class="p">*</span> <span class="n">k</span><span class="p">;</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Ergebnis ist {0}"</span><span class="p">,</span> <span class="n">ergebnis</span><span class="p">);</span>
<span class="n">ergebnis</span> <span class="p">=</span> <span class="p">(</span><span class="n">i</span> <span class="p">+</span> <span class="n">j</span><span class="p">)</span> <span class="p">*</span> <span class="n">k</span><span class="p">;</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Ergebnis ist {0}"</span><span class="p">,</span> <span class="n">ergebnis</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In diesem Beispiel kann man sehen, dass es zu zwei unterschiedlichen Ergebnissen kommt, abhängig davon, ob man die Klammern gesetzt hat oder nicht. Diese Fehler kann man nur durch gezieltes Testen oder Ausprobieren finden.</p>
<h4 id="haltepunkt-breakpoint">Haltepunkt (Breakpoint)</h4>
<p>Für andere logische Fehler kann es hilfreich sein, sich Haltepunkte im Programm zu setzten, um sich den momentanen Werte einer Variablen anzusehen. In diesem Beispiel wurde die Variable “Ergebnis” zwei Mal hintereinander auf unterschiedliche Wert gesetzt. Die erste Ausgabe zeigt den Wert, nach der ersten Berechnung, die zweite Ausgabe den Wert nach der zweiten Berechnung. Um nun nachvollziehen zu können, wann die Variable welchen Wert hat, kann man einen Breakpoint im Quellcode einfügen.</p>
<p class="pull-left"><img src="https://www.lernmoment.de/images/was-bedeutet-debuggen/ergebnis-punkt-vor-strich.png" alt="Ergebnis Punkt vor Strich Rechnung" /></p>
<p>In diesem Beispiel kann man sehen, dass es zu zwei unterschiedlichen Ergebnissen kommt, abhängig davon, ob man die Klammern gesetzt hat oder nicht. Diese Fehler kann man nur durch gezieltes Testen oder Ausprobieren finden.</p>
<p>Für andere logische Fehler kann es hilfreich sein, sich Haltepunkte im Programm zu setzten, um sich den momentanen Werte einer Variablen anzusehen. In diesem Beispiel wurde die Variable “Ergebnis” zwei Mal hintereinander auf unterschiedliche Wert gesetzt. Die erste Ausgabe zeigt den Wert, nach der ersten Berechnung, die zweite Ausgabe den Wert nach der zweiten Berechnung. Um nun nachvollziehen zu können, wann die Variable welchen Wert hat, kann man einen Breakpoint im Quellcode einfügen.</p>
<p><img src="https://www.lernmoment.de/images/was-bedeutet-debuggen/breakpoint.png" alt="Quellcode mit Breakpoint in Visual Studio" /></p>
<p>Während der Ausführung unterbricht das Programm an dieser Stelle und man kann sich die Variablen Werte bequem ansehen um Fehler oder ein bestimmtes Verhalten nachvollziehen zu können. In diesem Fall hat “Ergebnis” noch den Wert nach der ersten Berechnung, da diese Codezeile noch nicht ausgeführt wurde. Man kann nun Schritt für Schritt durch den Code gehen und jede einzelne Operation nachvollziehen. Finden muss man den Fehler jedoch immer noch selbst.</p>
<div class="notice">
Dies ist ein Gastartikel von Daniel Gustorff. Seit einiger Zeit unterstützt mich Daniel bei Entwicklungsarbeiten für Kunden. Als erfahrener Softwareentwickler beschäftigt sich Daniel viel mit der Interaktion zwischen Software auf einem Rechner und technischen Geräten (z.B. im Bereich der Gebäudeautomation). Er hält bei LernMoment die Fahne hoch für ein praktisches und pragmatisches Vorgehen. Daher freut es mich um so mehr, dass er nun auch seine Erfahrung mit dir teilt. DANKE!
<br />
Du erreichst Daniel unter:
<a href="http://github.com/gustda" title="Daniel Gustorff auf Github" target="_blank"><i class="fa fa-github-square"></i></a>
<a href="mailto:daniel@lernmoment.de" title="Schreib Daniel Gustorff eine Mail" target="_blank"><i class="fa fa-envelope-square"></i></a>
</div>
<p><a href="https://www.lernmoment.de/alle/was-bedeutet-debuggen/">Was bedeutet Debuggen?</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am May 02, 2018.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/erste-schritte-visual-studio-20172019-09-17 06:00:00 +0100T00:00:00-00:002017-05-19T07:00:00+02:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<blockquote>
<p><strong>UPDATE:</strong> Dieser Teil des Tutorials ist in einer <a href="/csharp-tutorial-deutsch/erste-schritte-visual-studio-2019/">neueren Version</a> (für Visual Studio 2019) verfügbar.</p>
</blockquote>
<p>Die ersten Schritte in Visual Studio können ganz schön kompliziert sein. In diesem Tutorial zeige ich dir Schritt für Schritt was du tun musst um deine erste C#-Anwendung mit <strong>Visual Studio 2017</strong> Community Edition zu erstellen. Dabei starten wir mit der Installation und hören auf mit einer fertigen (kleinen) Anwendung.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/e-F-iHSYpzU" frameborder="0" allow="encrypted-media" allowfullscreen=""></iframe>
<p>Egal ob du in deinem Beruf weiterkommen möchtest, im Studium mit den Informatikvorlesungen nicht zurecht kommst oder einfach für dich Programmieren lernen möchtest, in diesem kostenlosen C# Tutorial in Deutsch erfährst du alles, was du brauchst um deine erste (kleine) Anwendung zu erstellen.</p>
<p>Schritt für Schritt zeige ich dir wie du Visual Studio 2017 in der Community Edition installierst, damit dein erstes Projekt erstellst, was Quellcode ist, wie du Quellcode in C# schreibst, wie Quellcode kompiliert wird, was kompilieren überhaupt bedeutet und wie du deine eigene Anwendung in der Konsole ausführst.</p>
<div class="subscribe-notice">
<h5>Lerne alles über C# und professionelle Softwareentwicklung</h5>
<a href="https://www.udemy.com/course/einstieg-in-csharp-software-programmieren-wie-ein-profi/?couponCode=CS_20-0921_LMDE" class="notice-button">Hier geht's zum Online-Kurs "Einstieg in C#" >></a>
</div>
<h3 id="weitere-links">Weitere Links</h3>
<ul>
<li><a href="https://www.visualstudio.com/de">Visual Studio 2017</a> - kostenlose Community Edition.</li>
<li><a href="https://docs.microsoft.com/de-de/visualstudio/install/install-visual-studio">Offizielle Installationsanleitung</a> - hier hat Microsoft im Detail beschrieben was du bei der Installation machen und beachten sollst. Habe ich dir im Video aber soweit alles erklärt.</li>
<li><a href="https://docs.microsoft.com/de-de/visualstudio/ide/whats-new-in-visual-studio">Neues in Visual Studio 2017</a> - Artikel von Microsoft, der die wichtigsten Funktionalitäten in der aktuellen Version beschreibt.</li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/install/create-a-network-installation-of-visual-studio">Offline Installation</a> - beschreibt wie die benötigten Komponenten von Visual Studio 2017 runtergeladen werden können und dann vorbereitet werden um sie auf einem Rechner ohne Internetverbindung zu installieren. Diesen Artikel gab es auch in Deutsch, aber momentan ist er nur auf Englisch verfügbar.</li>
</ul>
<h3 id="der-komplette-quellcode-für-diese-folge">Der komplette Quellcode für diese Folge:</h3>
<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">HelloWorld</span>
<span class="p">{</span>
<span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Hallo Welt"</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Anwendung wird beendet durch drücken von 'Enter'!"</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Viel Erfolg für deine C# Anwendung</p>
<p>Jan</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/erste-schritte-visual-studio-2017/">UPDATE: C# Tutorial Deutsch - Erste Schritte</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am May 19, 2017.</p>
https://www.lernmoment.de/csharp-tutorial-deutsch/methodenaufruf-und-stack2016-12-22T06:00:00+01:002016-12-22T06:00:00+01:00Jan Suchotzkihttps://www.lernmoment.dejan@lernmoment.de
<blockquote>
<p>Schau dir auch die weiteren Folgen des <a href="/csharp-tutorial-deutsch/">C# Tutorial Deutsch</a> an.</p>
</blockquote>
<p>Den Teilnehmern meines Kurses <a href="/einstieg-sharp/">“Einstieg in C# - Software programmieren wie ein Profi”</a> biete ich die Aktion <em>#FragLernMoment</em> an. Das bedeutet, dass sie im Diskussionsforum eine Frage stellen können. Diese beantworte ich natürlich schriftlich, aber jede Woche gebe ich die Antwort zu einer Frage auch per Video.</p>
<p>Diese Folge des <em>C# Tutorial Deutsch</em> ist genau solch ein Video. Darin erkläre ich dir (sehr anschaulich ;) was der <em>Stack</em> ist und was er mit einem Methodenaufruf zutun hat. Die Frage dazu kam von einem Kursteilnehmer der zwar Methoden allgemein verstanden hatte sich aber nicht <em>bildlich</em> vorstellen konnte wie das mit der Wertübergabe und Rückgabe zur Laufzeit funktioniert.</p>
<p>Alles weitere erfährst du hier im Video:</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ma8wA5LmNXg" frameborder="0" allow="encrypted-media" allowfullscreen=""></iframe>
<div class="subscribe-notice">
<h5>Du willst mehr über Methoden erfahren?</h5>
<a href="https://www.udemy.com/course/einstieg-in-csharp-software-programmieren-wie-ein-profi/?couponCode=CS_20-0921_LMDE" class="notice-button">Hier geht's zum Online-Kurs "Einstieg in C#" >></a>
</div>
<h3 id="was-ist-ein-stack">Was ist ein Stack?</h3>
<p>Im Bereich von <em>Algorithmen und Datenstrukturen</em>, einem Teilgebiet der Informatik, wird ein <em>Stack</em> häufig mit <em>Keller</em> übersetzt. Du kannst Elemente von oben in den Keller legen und musst immer das zuletzt reingelegte zu erst raus nehmen.</p>
<p>Im Speichermanagement von <em>.NET</em> wird ein <em>Stack</em> verwendet um zur Laufzeit lokale Daten einer Methode zu speichern. Dabei bekommt jeder Methodenaufruf seinen eigenen <em>Stack-Frame</em>. In diesem Container legt die Laufzeitumgebung von .NET dann die ganzen Werte von Variablen ab.</p>
<p>Die allgemeine Funktionsweise eines <em>Stack</em> ist sehr gut auf <a href="https://de.wikipedia.org/wiki/Stapelspeicher">Wikipedia erklärt</a>.</p>
<h3 id="warum-braucht-ein-methodenaufruf-einen-stack-frame">Warum braucht ein Methodenaufruf einen Stack-Frame?</h3>
<p>Alles was in einer Methode lokal verwendet wird, wird lediglich während der Ausführung dieser Methode benötigt. Es ist allerdings möglich, dass eine Methode unterbrochen wird, weil sie eine andere Methode aufruft. Wenn dies geschieht, müssen alle Werte so wie sie momentan in der aufrufenden Methode sind gesichert werden.</p>
<p>Die aufgerufene Methode ihrerseits braucht allerdings auch einen Bereich wo ihre Werte gespeichert werden. Somit wird für jede Methode einfach ein <em>Stack-Frame</em> angelegt und auf den <em>Stack</em> gelegt. Ist diese Methode nun abgearbeitet, dann werden auch alle ihre lokalen Variablen gelöscht, denn diese werden später nie wieder gebraucht.</p>
<p>Damit lässt sich auch sehr anschaulich erklären warum zwei Methodenaufrufe (der gleichen Methode) komplett unabhängig sind. Es wird zwar immer der gleiche Quellcode ausgeführt, aber die Daten mit denen die Methode arbeitet sind jedesmal “neu”, weil mit jedem Aufruf der Methode ein neuer <em>Stack-Frame</em> angelegt wird. Das kann übrigens sehr häufig passieren, wenn eine Methode in einer Schleife (z.B. <em>foreach</em>) ausgeführt wird.</p>
<h3 id="weitere-links">Weitere Links</h3>
<p>Eine geniale Beschreibung von <em>Stack</em> und vielen weiteren Teilen des <em>.NET Speichermanagements</em> sind im (nur auf Englisch verfügbaren) Artikel <a href="https://www.simple-talk.com/dotnet/net-framework/net-memory-management-basics/"><em>“.NET Memory Management Basics”</em></a> beschrieben. Wenn dich das Thema interessiert und du ein wenig Englisch kannst, dann solltest du den Artikel unbedingt lesen.</p>
<p>Auch wenn ich im Quellcode zu diesem Video nichts besonderes gemacht habe, kannst du ihn <a href="https://gist.github.com/suchja/a08ffacdbdf23a9077a03b7510deeb15">hier anschauen</a> falls du etwas ausprobieren möchtest.</p>
<p>Viel Erfolg mit den nächsten Methodenaufrufen</p>
<p>Jan</p>
<p><a href="https://www.lernmoment.de/csharp-tutorial-deutsch/methodenaufruf-und-stack/">Der Stack und was beim Methodenaufruf passiert</a> veröffentlicht von Jan Suchotzki auf <a href="https://www.lernmoment.de">LernMoment.de</a> am December 22, 2016.</p>