DotNet-CSharp Skript 2016

Werbung
Fachhochschule Westküste
Hochschule für Wirtschaft & Technik
Wirtschaftsinformatik
.NET & C# - 2012
- C# - Programmierung
- .Net Klassenbibliothek
- Stand SS 2016
Prof. Dr. Burkhard Müller
.NET-Framework & C#.NET
Literatur zur Veranstaltung
Autor
Louis, Dirk
Kansy, Thorsten
Strasser, Shinja
Titel
Verlag
Visual C# 2012
Entwicklerbuch
Microsoft Press
Visual C# 2012
Grundlagen der Programmierung
Herdt-Verlag
VCSPNET2012
ISBN 978-3-86645-565-8
- Seite 2 -
.NET-Framework & C#.NET
Gliederung
A. Grundlagen & Strukturen ........................................................................ 7 1 Einführung in die .Net – Programmierung ............................................. 7 1.1 Visual Studio & .Net-Framework ......................................................... 8 1.2 Visual Studio - Starten & Beenden.................................................... 10 1.3 Ausgewählte Anwendungstypen ....................................................... 12 1.3.1 Konsolen – Anwendung ............................................................. 12 1.3.2 Windows-Anwendung ................................................................ 13 1.3.3 VSTO-Anwendung für Excel ...................................................... 16 1.4 VS-Dokumentation ............................................................................ 17 1.4.1 Zugang zur Dokumentation........................................................ 17 1.4.2 Installation lokaler Hilfeinhalte ................................................... 18 1.4.3 Dokumentationen ....................................................................... 19 1.5 Zusammenfassung ............................................................................ 20 2 Objektorientierte Programmierung – Theorie I.................................... 22 2.1 Differenzierung & Strukturen ............................................................. 22 2.2 Einstiegsbeispiel ............................................................................... 23 2.3 Strukturen der Programmiersprache C# ........................................... 26 2.3.1 Grammatik der Programmiersprache C# ................................... 26 2.3.2 Elemente der Programmiersprache C# ..................................... 27 2.4 Strukturen von Klassen ..................................................................... 29 2.4.1 Klassen & Objekte und deren Member ...................................... 30 2.4.1.1 Klassen <=> Objekte, Instanziierung ..................................... 30 2.4.1.2 Klassen-Member - Bestandteile von Klassen und Objekten .. 31 2.4.2 Klassen & Objekte in C# ............................................................ 32 2.4.2.1 Klassen der FCL ..................................................................... 33 2.4.2.2 Eigene Klassen ...................................................................... 35 3 .NET-Entwicklungsumgebung .............................................................. 37 3.1 Grundlagen des .NET-Framework .................................................... 37 3.1.1 Komponenten des .NET-Framework ......................................... 37 3.1.2 Kompilierungsphilosophie des .NET-Framework ....................... 38 3.1.3 Zusammenfassung .................................................................... 39 3.1.4 Veröffentlichung von Anwendungen .......................................... 40 3.2 Die IDE - Visual Studio .NET ............................................................ 41 3.2.1 Visual Studio und alternative Entwicklungsumgebungen .......... 41 3.2.2 Aufruf der Entwicklungsumgebung (IDE) in Visual Studio ......... 42 3.2.3 Speichern & Portieren von Projekten ......................................... 43 3.2.4 Komponenten der IDE ............................................................... 44 3.2.5 Generelle Einstellungen für die IDE ........................................... 45 3.3 C#-Programmierung in Visual Studio .NET....................................... 46 3.3.1 Anweisungen & Blöcke .............................................................. 46 3.3.2 Kommentare .............................................................................. 47 3.3.3 Konventionen für Bezeichner ..................................................... 48 3.3.4 Änderung von Bezeichnern........................................................ 49 - Seite 3 -
.NET-Framework & C#.NET
3.3.5 Anatomie von C#-Anwendungen ............................................... 50 3.3.5.1 Konsolen-Anwendungen ........................................................ 51 3.3.5.2 Windows-Anwendungen......................................................... 52 3.3.6 Debug-Fenster ........................................................................... 55 3.3.6.1 Vorgehensweisen ................................................................... 55 3.3.6.2 Debug-Ansichten .................................................................... 56 3.3.6.3 Anzeigen von Variablenwerte................................................. 57 3.3.7 Projektmappen-Explorer & Symbole .......................................... 58 B. Programmiersprache Visual C# ............................................................ 60 4 Exkurs: Klassen für die Konsolen-Programmierung .......................... 60 4.1 4.2 4.3 5 Console-Klasse ................................................................................. 60 Convert-Klasse .................................................................................. 60 Formatierung von Ausgaben ............................................................. 61 Datentypen I ............................................................................................ 64 5.1 Typen - Common Type System vs. Programmiersprache ................ 65 5.2 Differenzierung der Datentypen ........................................................ 66 5.2.1 Differenzierung der Typen ......................................................... 66 5.2.2 Werttpyen ................................................................................... 67 5.3 Datentypen in C# .............................................................................. 68 5.4 Methoden von Datentypen ................................................................ 70 5.5 Literale............................................................................................... 73 5.6 Variablen und Konstanten ................................................................. 74 5.7 Operatoren und Ausdrücke ............................................................... 76 5.8 Konvertierung von Datentypen.......................................................... 79 6 C#-Anweisungen .................................................................................... 81 6.1 Vom Problem zum Programm ........................................................... 82 6.1.1 Beispiel für Vorgehensweise...................................................... 83 6.1.1.1 Problemanalyse ...................................................................... 84 6.1.1.2 Struktogramm ......................................................................... 87 6.1.1.3 Codierung ............................................................................... 88 6.1.2 Grundsätzliches zur Problemanalyse ........................................ 89 6.1.3 Kontrollstrukturen ....................................................................... 90 6.2 Kontrollstrukturen .............................................................................. 91 6.2.1 Alternationen (Verzweigungen).................................................. 91 6.2.1.1 Einseitige Auswahl ................................................................. 92 6.2.1.2 Zweiseitige Auswahl ............................................................... 95 6.2.1.3 Mehrseitige Auswahl .............................................................. 98 6.2.1.4 Mehrstufige Auswahl ............................................................ 101 6.2.2 Iterationen ................................................................................ 104 6.2.2.1 Zählergesteuerte Iteration .................................................... 105 6.2.2.2 Bedingte Iteration - kopfgesteuert ........................................ 110 6.2.2.3 Bedingte Iteration - fußgesteuert .......................................... 113 6.3 Übungen .......................................................................................... 116 6.3.1 Endwertmethode ...................................................................... 116 - Seite 4 -
.NET-Framework & C#.NET
6.3.2 6.3.3 6.3.4 6.3.5 7 Degressive Abschreibung 1 ..................................................... 118 Degressive Abschreibung 2 ..................................................... 120 Prämienberechnung ................................................................. 122 Zinsrechnung ........................................................................... 125 Datentypen II - Array ............................................................................ 130 7.1 Grundsätzliches zum Array ............................................................. 131 7.2 Eindimensionales Array .................................................................. 133 7.2.1 Eindimensionales alphanumerisches Array ............................. 134 7.2.2 Eindimensionales numerisches Array ...................................... 136 7.2.3 Eindimensionales, variables numerisches Array ..................... 138 7.3 Zweidimensionales Array ................................................................ 140 7.3.1 Zweidimensionales numerisches Array ................................... 141 7.3.2 Zweidimensionales, variables numerisches Array ................... 143 7.4 Rechnen im Array ........................................................................... 145 7.4.1 Rechnen im eindimensionalen Array ....................................... 145 7.4.2 Rechnen im eindimensionalen, variablen Array ...................... 147 7.4.3 Rechnen im zweidimensionalen Array ..................................... 150 7.4.4 Rechnen im zweidimensionalen, variablen Array .................... 154 7.5 Übungen .......................................................................................... 158 7.5.1 Gewinn-Ermittlung (Array fix) ................................................... 158 7.5.2 Gewinn-Ermittlung (Array variabel) .......................................... 162 C. Klassen der FCL & Windowsanwendungen ...................................... 166 8 .NET-Entwicklungsumgebung - Teil 2 ................................................ 166 8.1 8.2 8.3 9 Ansicht der IDE ............................................................................... 167 Rückblick: Beispiel für Windows-Anwendung ................................. 169 Rückblick: Anatomie von Windows-Anwendungen ......................... 171 Objektorientierte Programmierung - Theorie Teil 2 .......................... 174 9.1 9.2 9.3 9.4 9.5 9.6 Klassen & Klassenmember ............................................................. 175 Vererbung & Instanziierung............................................................. 176 Vererbung bei Windows-Anwendungen .......................................... 177 Instanziierung bei Windows-Anwendungen .................................... 178 Klassen der FCL & Klassenmember ............................................... 179 Eigenen Klassen & Klassenmember ............................................... 181 10 Namespace System.Windows.Forms ................................................. 183 10.1 Strukturen des Namespace System.Windows.Forms ..................... 183 10.2 Überblick ......................................................................................... 186 10.3 Elementare Steuerelemente (Klassen) ........................................... 190 10.3.1 Button-Klasse ........................................................................... 191 10.3.2 Label-Klasse ............................................................................ 192 10.3.3 TextBox-Klasse ........................................................................ 193 10.4 Übungen - Elementares .................................................................. 194 10.4.1 Division zweier Zahlen ............................................................. 194 10.4.2 Rabatt-Berechnung .................................................................. 197 - Seite 5 -
.NET-Framework & C#.NET
11 DataGridView-Klasse ........................................................................... 200 11.1 DataGridView-Klasse - Überblick .................................................... 200 11.1.1 Grundlegende Strukturen......................................................... 201 11.1.2 Exkurs: Collection-Klasse ........................................................ 202 11.1.3 Columns- und Rows-Eigenschaft............................................. 203 11.1.4 Aufbau eines DataGridView-Objektes ..................................... 205 11.1.5 Schematische Darstellung von Rows & Cells .......................... 207 11.1.6 Variabler Zugriff auf Rows & Cells ........................................... 208 11.2 Berechnungen - Grid <=> Array ...................................................... 209 11.2.1 Dimensionierung des Arrays .................................................... 210 11.2.2 Übertragung der Daten: Grid => Array..................................... 211 11.2.3 Berechnungen im Array ........................................................... 213 11.2.4 Übertragung der Daten: Array => Grid..................................... 214 11.3 Optische Gestaltung des DataGridView-Objekts ............................ 216 11.3.1 Objekthierarchie ....................................................................... 217 11.3.2 Gestaltung durch CellStyle-Eigenschaften .............................. 219 11.3.3 Zugriff über Name-Eigenschaft ................................................ 221 11.3.4 Gestaltung durch CellStyle-Objekte ......................................... 222 11.4 Übungen & Fragen .......................................................................... 224 11.4.1 Kapital-Verlauf (Variante 1)...................................................... 224 11.4.2 Kapital-Verlauf (Variante 2)...................................................... 226 11.4.3 Endwert-Methode (Variante 1) ................................................. 228 11.4.4 Endwert-Methode (Variante 2) ................................................. 231 11.4.5 Lotto-Gewinn ............................................................................ 233 11.4.6 Prämien-Berechung ................................................................. 236 11.4.7 Kosten- und Gewinnvergleich .................................................. 240 11.4.8 Break-Even-Analyse ................................................................ 247 11.4.9 Verteilung von Gemeinkosten .................................................. 250 - Seite 6 -
.NET-Framework & C#.NET
A. Grundlagen & Strukturen
In diesem Kapitel werden die Grundlagen für den Umgang mit der Visual Studio Umgebung, der sogenannten IDE (Integrierte Entwicklungsumgebung /
Integrated Development Environment), gelegt.
 Struktur der IDE
 Ausgewählte Anwendungstypen
 Klassen & Objekte
1 Einführung in die .Net – Programmierung
In diesem Abschnitt wird zum einen ein Überblick über die .Net-Entwicklungsumgebung gegeben, damit jedem Studierenden die Strukturen der Umgebung und der zu erstellen Programme verständlich sind. Anhand von drei
Beispielen werden die für BWL-Studierenden typischen .Net-Anwendungenstypen vorgeführt.
Wichtig
 Nicht alles werden Sie gleich im Detail verstehen. Das kann auch nicht
anders sein und macht an dieser Stelle auch nichts. Es geht erst einmal
nur um einen Überblick – die Vertiefung folgt in den späteren Kapiteln.
 Des Weiteren werden einige Fachbegriffe in diesem ersten Kapitel den
bereits programmiererfahrenen Studierenden etwas unprofessionell vorkommen. Ertragen Sie es mit Fassung, die exakten Definitionen werden
zum einem späteren Zeitpunkt eingeführt.
Inhalte
 Aufruf und Beenden der IDE
 Struktur und Speichern von VS-Projekten
 Beispiele für Anwendungstypen
 Konsolen-Anwendungen
 Windows-Anwendungen
 VSTO-Anwendungen für Excel
 Kompilieren und verteilen von VS Projekten
- Seite 7 -
.NET-Framework & C#.NET
1.1 Visual Studio & .Net-Framework
Visual Studio-Entwicklungsumgebung - IDE
 Eine Entwicklungsumgebung, auch Integrated Development Environment oder kurz IDE, ist eine Toolbox, die Werkzeuge für eine komfortable Programmierung zur Verfügung stellt.
 Visual Studio - kurz VS - ist die Entwicklungsumgebung von Micrososft für
die .Net-Programmierung
 Diese ist kostenpflichtig, wird aber Studierenden über die Hochschulen kostenlos zur Verfügung gestellt.
 .Net – Programme müssen nicht zwingend mit Visual Studio entwickelt werden; es reicht auch ein Editor wie Notepad o.ä. aus. Dieser ist dann nur
nicht so komfortabel.
.Net-Framework
 Unabhängig von der VS-IDE stellt Microsoft jedem Entwickler kostenfrei das
.Net-Framework, auch Framework Class Library oder kurz FCL, zur Verfügung.
 Diese Klassenbibliothek (Class Library) enthält eine Vielzahl von Klassen,
die für die Programmierung benötigt werden. Beispiele für Klassen sind die
aus den üblichen Windows-Anwendungen bekannten Elemente wie Button,
Label usw.
 Diese Klassenbibliothek und ein Editor sind die Minimalanforderungen für
die .Net-Programmierung.
Strukturen der .Net-Entwicklungsumgebung - IDE
Die Elemente in der DIE sind:
 In der .Net-Klassenbibliothek sind die wichtigesten Klassen (Button, Label
usw.) zusammengefasst.
 Das Common Type System stellt die Datentypen, die zum Speichern von
Informationen benötigt werden, zur Verfügung.
 Die Programmiersprachen und der Editor sind für das Schreiben eines
Programmes erforderlich.
- Seite 8 -
.NET-Framework & C#.NET
Klassen & Objekte
Der zentrale Begriff der objektorientierten Programmierung ist der der Klasse
bzw. des Objekts.
 Eine Klasse ist die Vorlage - mache sagen auch der BluePrint - für etwas.
 Dieses Etwas kann z.B. ein Button oder ein Label sein. Im Grunde liegt jedem Element, das Ihnen von einer Windows-Oberfläche her bekannt ist,
eine Klasse zugrunde.
 Die Vorlage wird als Klasse, das konkrete Element auf der Windowsoberfläche als Objekt bezeichnet.
 Man kann zur Veranschaulichung auch den Vergleich mit dem Objekt
"Tisch" heran ziehen. Die Konstruktionszeichung eines Tisches wäre die
Klasse, der konkrete Tisch wäre das Objekt.
Wichtig
 Die Klasse enthält die Struktur, d.h. welche Platzhalter sind für diese Art
von Objekten notwnedig sind, aber keine konkreten Werte
 Das Objekt baut auf dieser Struktur der Klasse auf enthält dann die konkreten Werte
Anmerkung
Der Begriff "Platzhalter" ist im Zusammenhang mit der Programmierung nicht
sehr professionell - die korrekte Definition erfolgt aber später!
- Seite 9 -
.NET-Framework & C#.NET
1.2 Visual Studio - Starten & Beenden
Einstieg in Visual Studio .Net
Nachstehend finden Sie als ersten das Einstiegsfenster von VS.Net 2012.
Aktivieren Sie dort über die Menü-Items -> Datei -> Projekt -> neu
das nachstehende Fenster zum Erstellen eines neuen Projektes aus.
- Seite 10 -
.NET-Framework & C#.NET
Wichtige Anmerkungen:
 Beim erstmaligen Aufruf von VS.Net (nach der Installation) werden Sie nach
Ihrer Programmiersprachen-Umgebung gefragt.
 Wenn Sie dort Visual C# angegeben haben erscheint auch Visual C# in
dem linken Teil des Fensters als erstes als Vorlage. Andere Sprachen z.B. Visual Basic - finden unter dem Knoten "Andere Sprachen".
 Sollten Siem beim ersten Aufruf z.B. versehentlich als typische Sprachumgebung Visusal Basic gewählt haben, so erscheint an erster Stelle
eben Visual Basic und Sie finden C# unter dem Knoten "Andere Sprachen".
 In diesem Skript wird die Programmiersprache C# zugrunde gelegt. Es ist
wichtig, dass auch nur Anwendungstypen unterhalb des Knotens "Visual
C#" ausgewählt werden.
 In dem mittigen Hauptfenster ist die gewünschte Vorlage zu wählen. Hier
sind vorerst nur Konsolen- oder WindowsForms- Anwendungen relevant.
Die entsprechende Vorlage ist durch einmaliges Klicken zu selektieren.
 In dem unteren Teil des Fensters ist der Name des Projektes und der
Speichort anzugeben. Der Name des Projekts ist dann auch der Name des
Pfades, unter dem alle Projektdateien gespeichert werden. Vermeiden Sie
bei dem Bezeichner Sonderzeichen und Leerschritte.
- Seite 11 -
.NET-Framework & C#.NET
1.3 Ausgewählte Anwendungstypen
1.3.1 Konsolen – Anwendung
IDE für Konsolen-Anwendungen
Beim Start der IDE für die Entwicklung einer Konsolen-Anwendungen wird
das nachstehende Fenster mit dem vorbereiteten Code geöffnet.
Struktur einer Konsolen-Anwednung




Using-Anweisungen für die Einbindung der Namespaces
Namespace
Klasse
Methode (allgemein Member der Klasse)
Code Erstellung
Dieser Code ist um die unten markierten Zeilen zu ergänzen.
Programm-Code
Programm - Ausführung (Laufzeit)
 Funktions-Taste <F5> oder über das
 Menü „-> Debuggen -> Debugging starten“
Zur Laufzeit wird dann der Text „Hello World“ auf den Bildschirm ausgegeben. Durch die <Enter>-Taste wird zur IDE zurückgekehrt.
- Seite 12 -
.NET-Framework & C#.NET
1.3.2 Windows-Anwendung
IDE – für Windows-Anwendungen
Bei der Entwicklung von Windows-Anwendungen ist die Entwicklung in zwei
Komponenten zu differenzieren:
 Programmierung in der bekannten Code-Ansicht
 Gestaltung der Oberfläche (GUI – Graphic User Interface), d.h. des Formulars oder der Form, in der Designer-Ansicht.
Klassen für die GUI-Gestaltung (Controls)
Projekt-Explorer
Form
Member (Eigenschaften)
des aktiven Objektes
- Seite 13 -
.NET-Framework & C#.NET
Erstellung der Form (Designer der IDE)
 Instanziierung einer Klasse
 Ziehen einer Klasse (Vorlage) aus der ToolBar auf die Form
 Anmerkung
 ToolBar -> Klasse
 Formular -> Objekt oder Instanz
 Optische Veränderung des Objekts
 Anklicken des Objektes (Objekt selektieren)
„Anfasser“ am Rand des Objektes sind aktiv
 Größenveränderung
durch Ziehen der Anfasser
 Verschiebung
 mit gedrückte linker Maus-Taste verschieben
 Eigenschaften (Member) von Klassen / Objekten
 Ist ein Objekt selektiert (Anfasser des Objektes sind sichtbar), können
auch über das Eigenschaften-Fenster die Werte der Eigenschaften des
Objektes geändert werden.
 Zentrale Eigenschaften
 Size-Eigenschaft für Größe des Objektes
 Location-Eigenschaft für die Position - ausgehend von der linken
oberen Ecke der Form – des Objektes.
 Text-Eigenschaft für die Beschriftung des Objektes
 Die endgültige Form könnte z.B. das folgende Layout besitzen.
 Anmerkung
Allerdings geht auch die Arbeit mit Designer nicht ohne Code. Zu einer mit
dem Designer entworfene Form wird von der IDE automatisch der Code erzeugt, der die Objekte zur Laufzeit anzeigt. Wo dieser Code abgelegt wird,
wird später erläutert.
- Seite 14 -
.NET-Framework & C#.NET
Erstellung des Codes – Ereignisorientierte Methoden
 Im Gegensatz zu Konsolen-Anwendung werden Windows-Anwendung über
Objekte und deren Ereignisse (Events) gesteuert (Beispiel: Objekt Button
und Click-Event). Dieses bedeutet, dass das Programm erst ausgeführt
wird, wenn bei einem Objekt ein bestimmtes Event ausgelöst wird.
 In den Code für ein ereignisorientiertes Programm – besser eine ereignisorientierte Methode – gelangt man durch das doppelte Klicken auf das gewünschte Objekte im Designer. Will man folglich zu dem obigen Button
„btnStart“ eine Methode erstellen, so gelangt man durch den Doppelklick in
den nachstehenden bereits generierten Code.
 Automatisch generierter Code
 Die Methode, die beim Klicken des Button „btnStart“ und „btnEnde“ (mit der
Beschriftung „Ausgabe“) ausgeführt wird, ist nachstehend abgebildet.
Laufzeit
Nach dem Klicken (Click-Event) auf den Button „btnStart“ erscheint in dem
Label „lblAusgabe“ der Text „Hello World“. Der Text wird folglich dadurch
angezeigt, dass der Text-Eigenschaft des Labels
- Seite 15 -
.NET-Framework & C#.NET
1.3.3 VSTO-Anwendung für Excel
IDE für Excel-Anwendung
Bei VSTO-Applikationen (Visual Studio Tools for Office) wird an Stelle der
Form das Objekt der entsprechenden Office-Anwendung als Vorlage verwendet. Bei dem nachstehenden Beispiel dient daher ein Excel-Sheet als
Vorlage.
Code
Form
- Seite 16 -
.NET-Framework & C#.NET
1.4 VS-Dokumentation
1.4.1 Zugang zur Dokumentation
Die VS-Dokumentation verfügt über eine Suchfunktion durch eine Freitextsuche oder durch vorgeschlagene Knotenpunkte sowie innerhalb des Codes
auch über eine kontextsensitive Hilfe. Je nach Fragestellung sind unterschiedliche Zugägne zur Dokumentation sinnvoll.
 F1-Taste
Befehl oder Objekt makrieren und drücken der F1-Taste, so öffnet sich
die Hilfe zu genau diesem Befehl.
 Struktur-Knotenpunkte
Wissen Sie nicht, welchen Befehl Sie gerade benötigen, ist es sinnvoll,
entweder die Freitext-Suche zu nutzen oder über die Knotenpunkte in der
Doku zu suchen. Dies wird weiter unten noch erläutert.
Hilfe-Einstellungen
 Quelle festlegen
Zuerst ist wichtig, wie die Hilfetexte dargestellt und von wo diese Texte geladen werden sollen. Über "Hilfe" -> "Hilfeeinstellung festlegen" gelangt man
zu den entsprechenden Optionen. Die Hilfe kann entweder im Browser oder in einem Help Viewer angezeigt werden.
 Hilfeinhalte hinzufügen und entfernen
Das Laden der Hilfe Inhalte erfolgt über "Hilfeinhalten hinzufügen und entfernen". Der Prozeß zur Verwaltung der Hilfe-Downloads wird in einem gesonderten Fenster beschrieben.
- Seite 17 -
.NET-Framework & C#.NET
1.4.2 Installation lokaler Hilfeinhalte
In diesem Abschnitt wird die lokale Installation des Hilfetextes beschrieben.
Das nachstehende Fenster zeigt die typische Ansicht dieser Installationsumgebung.
 Im linken Teil des Fensters werden die bereits installierten Hilfen angezeigt.
 Im mittleren Teil werden alle verfügbaren Inhalte verwaltet, d.h. deren
Status angezeigt. Die Aktion steht auf
 Entferner für bereits installietre Hilfen, dike wieder gelöscht werden sollern.
 Abbrechen für selektierte Hilfen, dier wieder deselektiert werden sollen.
 Hinzufügen für Hilfen, die noch selektiert werden können.
 Im rechten Teil des Fensters werden die Hilfen angezeigt, die selektiert
und installiert werden sollen. Die endgültige Installation erfolgt erst, wenn
Button "Aktualisieren" geklickt wurde.
- Seite 18 -
.NET-Framework & C#.NET
1.4.3 Dokumentationen
Innerhalb der Dokumentation gibt es zwei wichtige Handbücher.
 Zunächst gibt es das Visual C# Programmier-Handbuch, dsas sämtliche
Befehle der Sprache C# beschreibt.
 Weiterhin gibt es das Handbuch zur die .NET-Klassenbibliothek, welches
die Klassen bzw. Objekte der Bibliothek beschreibt.
Dokumentation zur Programmiersprache Visual C#
Unter dem Knoten C#-Referenz ist das Handbuch für die Programmiersprache
C# zu finden. Dort werden die Details zur Programmiersprache erläutert.
Dokumentation zur .NET-Klassenbibliothek
Unter dem Knoten .NET Framework-Klassenbibliothek ist die Beschreibung aller .NET Klassen zu finden, die aus Gründen der Übersichtlichkeit in sogenannten Namespaces organisiert sind.
- Seite 19 -
.NET-Framework & C#.NET
1.5 Zusammenfassung
Strukturen des .Net-Frameworks
 IDE - Integrated Development Environment: Visual Studio (kostenpflichtig)
 Basisklassen-Bibliothek; FCL (Framework Class Library)/ BCL (Base
Class Library)
 Aufruf & Beenden von VS.Net
 Struktur der IDE
 Code-Ansicht <=> Designer-Ansicht
 Eigenschaftenfenster
 Toolbar; Toolbar
Anwendungstypen
 Konsolen-Anwendungen
 Windows-Anwendungen
 VSTO-Anwendungen (Visual Studio Tools for Office) usw.
Aufbau von Konsolen-Anwendungen
 using-Anweisungen für einzubindende Namespaces
 Struktur: Namespace -> Klasse -> Main-Methode
Aufbau von Windows-Anwendungen
 using-Anweisungen für einzubindende Namespaces
 Strukur: Namespace -> Klasse Form -> Konstrukutor; Ereignisbasierte
Methoden
- Seite 20 -
.NET-Framework & C#.NET
C#-Syntax-Regeln
 Kommentierung im Code
 Semikolon als Anweisungsende
Klassen & Objekte
 Differenzierung Klassen <=> Objekte
 Member-Arten
 Eigenschaften
 Methoden
 Ereignisse
 Konstruktor
 Ansprechen von Objekten & Membern im Code
 Wichtige Klassen
 Console
 Button
 Label
Methoden
 vordefinierte Methoden
 this.Close();
 Console.WriteLine();
 selbstdefinierte Methoden; ereignisbasierte Methoden
 Erzeugng durch Doppelklick im Desinger
 Bezeichner: Bezeichner des Objekts & Event
Änderung von Eigenschaften
 Änderungen im Designer
 Änderung im Code durch Zuweisungs-Anweisung
Umgang mit der Online-Dokumentation
 Zugang zur C#-Hilfe und deren Aufbau
 Zugang zur .Net-FCL-Hilfe und deren Aufbau
- Seite 21 -
.NET-Framework & C#.NET
2 Objektorientierte Programmierung – Theorie I
Dieses Kapitel befasst sich noch einmal vertiefend mit den Strukturen der Objektorientierten Programmierung (kurz: OOP). Da der Begriff OOP bereits
aus den beiden Bestandteilen objektorientiert und Programmierung besteht,
folgt dieses Kapitel auch dieser Differenzierung.
2.1 Differenzierung & Strukturen
Der zentrale Begriff der modernen Programmierung ist der der Objektorientierten Programmierung. Mit den Begriffen „Objektorientierung“ und „Programmierung“ sind die zwei Säulen, auf denen auch dieses Skript basiert, benannt.
Die Differenzierung in Klassen und Programmierung könnte auch als falsch
angesehen werden. Der Grund liegt darin, dass die Klassen – wie z.B. die Button-Klasse - natürlich mit Hilfe einer Programmiersprache entwickelt worden
sind, die Programmierung daher immanent ist.
Struktur des Manuskripts
B. Programmiersprache Visual C#
Im zweiten Teil des Skripts befassen wir uns nun genauer mit der Sprache
C# und lernen dabei beispielsweise das Grid (Tabelle) und das Array (Rechenbereich einer Tabelle) kennen. In der Sprache gilt es, wie oben erläutert, sprachspezifische Ausdrücke und Zuweisungen kennenzulernen. Diese
Sprachspezifikationen gelten in sämtlichen C#-Anwendungen.
C. Klassen der .NET Framework Class Library & Windowsanwendungen
Im dritten Teil des Skripts befassen wir uns nun mit der o.g. .NET-Umgebung. Mithilfe der Sprache C# wird innerhalb des .NET-Frameworks kommuniziert. Das .NET-Framework selbst beinhaltet Klassen, die bei der Programmierung helfen. Sie beinhalten immer Methoden(), Ereignisse und Eigenschaften. So beinhaltet beispielsweise die Klasse Convert die Methode
.ToDouble(), somit kann ein Wert eingelesen werden und in eine Zahl konvertiert werden. Dies ist zunächst einmal sprachunabhängig. Die .NET-Klassenbibliothek, die nur in der .NET-Umgebung vorhanden ist, beinhaltet also
nützliche, bereits "vorbereitete" Befehle. Es ist daher sinnvoll, die Klassen
und somit auch die Methoden(), Eigenschaften und Ereignisse des .NETFrameworks zu nutzen.
- Seite 22 -
.NET-Framework & C#.NET
2.2 Einstiegsbeispiel
Zu Beginn dieses Abschnittes steht wieder eine kleine Konsolen-Anwendung,
an der die zentralen Erläuterungen zur
 Programmiersprache und zur
 Klassenbibliothek
erfolgen werden. Bei diesem Beispiel sollen zwei Zahlen eingegeben und das
Produkt dieser beiden Zahlen ausgegeben werden. Der nachstehende
Screenshot zeigt den Ablauf.
Code
//Deklarationen double faktor1, faktor2, produkt; //Prozedur Console.Title = "Einstiegsbeispiel"; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Multiplikation zweier Zahlen"); Console.WriteLine(); //Eingabe Console.Write("1. Faktor : "); faktor1 = Convert.ToDouble(Console.ReadLine()); Console.Write("2. Faktor : "); faktor2 = Convert.ToDouble(Console.ReadLine()); //Berechnung produkt = faktor1 * faktor2; //Ausgabe Console.WriteLine(); Console.WriteLine("Produkt : {0,10:N}", produkt); Console.ReadLine();
- Seite 23 -
.NET-Framework & C#.NET
Deklaration von Variablen
Variablen dienen der temporären Speicherung von Werten.
 Variablen
 Eine Variable ist ein Speicherplatz im Hauptspeicher des Rechners
 Beim Ausschalten des Rechners bzw. beim Beenden des Programms
wird diese wowieder gelöscht
 Innerhalb einer Programmiersprache wird eine Variable mit einem Bezeichner benannt, was die Verwendung deutlich vereinfacht,da man
nicht mit numerischen Adresse sondern mit Namen arbeiten kann.
 Bezeichnung einer Variablen
 Die Bezeichnung einer ist grundsätzlich beliebig, unterliegt aber bestimmten Konventionen.
 Verwendung selbstsprechender Bezeichner.
 Lokale Variablen beginnen mit einem kleinen Buchstaben
 Sonderzeichen und Leerzeichen sind nicht zulässig.
 Typ
 Mit dem Typ wird festgelegt, was in der Variablen gespeichert werden
kann. So ist beispielsweise der Type double dafür geeignet reelle Zahlen aufzunehmen; Buchstaben sind in diesem Typ nicht speicherbar.
 Deklaration
Die Deklaration einer Variablen erfolgt durch die folgenden Anweisung erfolgen:
double faktor1;
double faktor1, faktor2, produkt;
Speichern und Lesen von Werten
Eine Wertzuweisung erfolgt durch das Gleichheitszeichen = .
faktor1 = Convert.ToDouble(Console.ReadLine());
produkt = faktor1 * faktor2;
Mathematische Gleichheit vs. Zuweisung
Die Zuweisung ist keine mathematische Gleichheit. D.h. die Ausdrücke der
Seiten dürfen nicht vertauscht werden. Es gilt immer:
linke Seite = rechte Seite
Ziel = Quelle
Folgt in der Mathematik aus A=B auch B=A, so gilt dieses in der Informatik
nicht.
- Seite 24 -
.NET-Framework & C#.NET
Typ-Gleichheit
Grundsätzlich muss auf beiden Seiten der Zuweisung der gleiche Datentyp
stehen.
Die folgende Anweisung ist fehlerhaft, da aus dem Tastaturpuffer auch Zeichenketten übergeben werden können und diese nicht vom Typ double
sind.
faktor1 = Console.ReadLine();
Diese Anweisung ist korrekt, da die Ausdrücke auf beiden Seiten der Zuweisung vom Typ double sind.
produkt = faktor1 * faktor2;
Konvertierung
Um die Gleichheit bei einer Zuweisungs-Anweisung herzustellen existieren
Konvertierungsmethoden. Ein Beispiel sind die Methoden der ConvertKlasse, mit der imnachstehenden Beispiel die Informationen des Tastaturpuffers in den Typ double konvertiert werden. Das führt aber zu einem Fehler, wenn die Informationen z.B. alphanumerisch sind.
faktor1 = Convert.ToDouble(Console.ReadLine());
- Seite 25 -
.NET-Framework & C#.NET
2.3 Strukturen der Programmiersprache C#
Im den nachstehenden Kapiteln wird die Struktur der Programmiersprache C#
erläutert. Es ist noch einmal darauf hinzuweisen, dass dieses von der Beschreibung der Klassenbibliothek, die die Klassen bzw. Objekte beinhaltet, zu
unterscheiden ist.
2.3.1 Grammatik der Programmiersprache C#
Grammatik einer Programmiersprache
„In dieser Beschreibung wird die Syntax der C#-Programmiersprache unter
Verwendung zweier Grammatiken dargestellt. Die lexikalische Grammatik
definiert, wie mittels Unicode-Zeichen Zeilenabschlusszeichen, Leerraum,
Kommentare, Token und Präprozessordirektiven gebildet werden. Die syntaktische Grammatik definiert, wie aus den aus der lexikalischen Grammatik resultierenden Token C#-Programme gebildet werden.“
Lexikalische Grammatik
 Lexikographie  Erstellung von Wörterbüchern (Sprachwissenschaften).
 Analog einer „normalen“ Sprache werden in der lexikalischen Grammatik
einer Programmiersprache die Grundlagen der Sprache definiert, wie z.B.
 Zeichenvorrat (welche Zeichen dürfen verwendet werden)
 Schlüsselworte (welche Wort dürfen gebildet werden)
 Kommentare (Verwendung von Kommentaren)
 Operatoren (zur Verknüfung)
…
Syntaktische Grammatik
 Syntax  Satzlehre (Sprachwissenschaften),
Regeln des Satzaufbaus, z.B. der Struktur von Haupt- und Nebensätzen
usw.
 Analog gilt bei Programmiersprache, dass durch die syntaktische Grammatik die Regeln für die Formulierung von
 Ausdrücke
 Aufbau von Anweisungen (Schleifen, Fallunterscheidungen, …)
 Struktur von Namespaces, Klassen und anderer Typen
…
festgelegt werden.
Prüfung der Grammatik durch den Compiler
 Die grammatikalische Prüfung erfolgt durch den C#-Compiler:
 Prüfung während der Codierung innerhalb der IDE
 Prüfung durch den Compiler vor der Übersetzung
- Seite 26 -
.NET-Framework & C#.NET
2.3.2 Elemente der Programmiersprache C#
Bei einer Programmiersprache werden die definierten Worte als Schlüsselwörter bezeichnet.
 Sie sind zu unterscheiden von frei wählbaren "Worten", wie z.B. den Bezeichner von von Variablen.
 Die Schlüsselworte sind reserviert, d.h. es darf zum Beispiel keine Variable so bezeichnet werden wie ein Schlüsselwort.
 Im Editor werden Schlüsselwort dunkelblau dargestellt und sind so gut erkennbar.
Differenzierung der Schlüsselwörter
Im Folgenden geht es darum, die Vielzahl der Schlüsselwörter aus Gründen
der Übersichtlichkeit zu differenzieren.
 Auf einer ersten Stufe lassen sich die folgenden zwei Gruppen bilden:
 Schlüsselwort, die im Zusammenhang mit den Datentypen Verwendung finden. Das ist zum Beispiel double bei der Deklaration einer Variablen.
 Schlüsselwort der zweiten Gruppe stehen hingegen im Zusammenhang mit Anweisungen, zum Besisiel einer Fallunterscheidung oder einer Schleife.
 Innerhalb dieser Gruppen lassen sich die Schlüsselworte dann weitere
differenzieren, was die weiter unten stehende Grafik veranschaulicht.
- Seite 27 -
.NET-Framework & C#.NET
Struktur des Vorlesungsmaterials
Bezug zum Beispiel
- Seite 28 -
.NET-Framework & C#.NET
2.4 Strukturen von Klassen
Verwendung von Klassen
Bei allen hellblau dargestellten Elementen (Convert- und Console-Klasse)
handelt es sich um Klassen.
Mitglieder / Member von Klassen
Member können sein




Eigenschaften (Merkmale)
Methoden (Fähigkeiten)
Ereignisse
Konstruktor
Verwendung von Eigneschaften und Methoden
 Setzt man nach dem Klassen-Bezeichner einen Punkt so lässt sich dann
aus der eingeblendeten Auswahlliste die gewünschte Eigenschaft oder
Methode auswählen.
 Selektiert man das gewünschte Member durch Klicken, wird rechts neben
der Liste ein kurzer Hilfetext eingeblendet.
- Seite 29 -
.NET-Framework & C#.NET
2.4.1 Klassen & Objekte und deren Member
Objekte sind die zentralen Elemente moderner Programmierphilosophien.
Objektorientierte Programmierung kurz OO.
Objekte
 Alles ist ein Objekt ("Everything ist an object")
 Beispiele
 Button „Ende“,
 Hund „Kalle“
 Schreibtisch.
2.4.1.1Klassen <=> Objekte, Instanziierung
Klasse  Objekt
Klasse

Vorlage, Blue Print
Objekt
konkretes Element
Beispiele
Konstruktuonszeichnung

Schreibtisch
Gene

Hund
Button (Toolbar)

Ende-Button (Form)
Instanziierung
Grundsatz
Eine Klasse muss erst instanziiert werden, damit die Eigenschaften und Methoden der Klasse genutzt werden können!
Ausnahme (statische Member)
Aber es gibt leider Ausnahmen, die dieses Prinzip durchbrechen: manchmal
beißen die genetischen Grundlage eben doch
! Das ist zwar nicht in der
realen Welt denkbar, jedoch in der Informatik und hier hinken dann die Vergleiche doch etwas.
- Seite 30 -
.NET-Framework & C#.NET
2.4.1.2Klassen-Member - Bestandteile von Klassen und Objekten
Jedes Klasse bzw. jedes Objekt - wie eine Button oder ein Lebewesen – besitzt verschiedene Arten von vorgegebenen Informationen, die nachstehend
kategorisiert und erläutert werden sollen.
Eigenschaften (Properties)
Eigenschaften: statischer Charakter, beschreiben ein Objekt
Ereignisse (Events)
Ereignisse: z.B. das Klicken auf ein Objekt => löst i.d.R. eine Methdoe aus
Methoden
Methoden machen die eigentliche Leistungsfähigkeit von Objekten aus. So
existieren bspw. bei der Klasse „Console“ die Methode „WriteLine“, die die
Ausgabe von Texten auf dem Bildschirm ermöglicht.
 Vordefinierte Methoden
Biese bereits vordefinierten Abläufe bezeichnet man im Zusammenhang mit
der OOP als vordefinierte Methoden. So gibt es bei der Klasse „Console“
mit „ReadLine“ und „WriteLine“ Methoden, die bereits bei der Klasse fest implementiert - also vordefiniert - sind.
 Selbstdefinierte Methoden
Da vordefinierte Methoden häufig nicht ausreichend sind, können zusätzlich
neue Methoden implementiert werden. Der Entwickler schreibt kleine Programme - Methoden -, die beim Auftreten von Ereignissen bei einem Objekt
ausgeführt werden. Klickt der Anwender auf den Button zum Ausgabe, gibt
das Programm den text "Hello World" auf einem Label aus. Zugegeben: das
ist nicht sehr anspruchsvoll; es ist aber eine erste selbstdefinierte Methode.
 Überladene Methoden
Methoden, die den gleichen Namen besitzen aber unterschiedliche Eingaben erfordern, bezeichnet man als überladene Methoden. So existieren z.B.
bei der Methode „WriteLine“ 18 Überladungen, die sich nach dem was gerade ausgegeben werden soll - Zahl, Buchstaben usw - unterscheiden.
 Statische Methoden; Instanz-Methoden
Will man mit einer Klasse arbeiteten, muss sie wie eingangs erläutert, erst
instanziiert werden. Die statischen Methoden bilden dabei eine Ausnahme.
Bestimmte Methoden, die direkt von der Klasse aus aufgerufen werden können - für die nicht erst eine Instanz (ein konkretes Objekt) notwendig ist,
werden als statische Methoden bezeichnet.
Konstruktor-Methode
Bei der Instanziierung kommt eine besondere Methode zum Einsatz, die
zwar bei Lichte betrachtet auch nur eine Methode ist, aber mit der Bezeichnung Konstruktor in besondere Weise hervorgehoben wird. Der Konstruktor
ist somit nur bei der Instanziierung der Klasse von Relevanz ist.
- Seite 31 -
.NET-Framework & C#.NET
2.4.2 Klassen & Objekte in C#
Das Thema Klassen kann aus zwei Perspektiven betrachtet werden.
 Verwendung der Klassen der FCL
 Erstellung eigener Klassen
Hierarchie
- Seite 32 -
.NET-Framework & C#.NET
2.4.2.1Klassen der FCL
Die auf der vorherigen Seite dargestellt Hierarchie soll jetzt noch einmal an der
Dokumentation der Klassenbibliothek veranschaulicht werden.
Namespaces der FCL
Namespace System
- Seite 33 -
.NET-Framework & C#.NET
Beispiel: Klasse Console
Öffnet man als nächsten den Knoten für die Klasse Console (und selektiert die
Klasse durch Klickt), so werden im linken Teil der Dokumentation die bekannten Membergruppen und im rechten Teil die Member im Detail angezeigt.
 Vordefinierte Methoden
Grundsätzlich handelt es sich bei den Klassen der FCL immer um vordefinierte Methoden.
 Statische Methoden
In der Methodenliste steht in der ersten Spalte bei allen Methoden ein rotes
"S", was für statische Methoden steht.
 Überladene Methoden
 Konstruktor-Methode
Eine Konstruktot-Methoide existiert bei Console-Klasse nicht.
- Seite 34 -
.NET-Framework & C#.NET
2.4.2.2Eigene Klassen
Auch wenn vorerst die Entwicklung eigener Klassen nicht im Vordergrund
steht, ist ein Grundverständnis für die Programmierung notwendig.
Sturktur einer Konsolen-Anwendungen
Gut nachvollziehbar auch hier, dass den Using-Anweisungen (werden weiter
unten besporchen) mit Namespace, Klasse und Main-Methode eine identische
Strukutr zu finden ist. In diesem Fall sehr simple, da innerhalb des Namespaces mit der Klasse Program nur eine Klasse und innerhalb dieser Klasse
mit der Main-Methode nur eine Methode existiert.
- Seite 35 -
.NET-Framework & C#.NET
Einbindung von Namespace-Bibliotheken
Die Using-Anweisungen dienen der Einbindung von Klassen eines Namespaces. Hierdurch kann die Programmierung vereinfacht werden. Bisher
wurde die Writeline()-Methode wie folgt verwendet:
Console.WriteLine("Multiplikation zweier Zahlen");
Die Klasse Console ist Mitglied des Namespaces System. Würde man die entsprechende Using-Anweisung ganz oben im Code deaktivieren, könnte auf die
Klasse Console nicht mehr zugegriffen werden, da dieser Namespace diesem
Projekt nicht mehr bekannt ist.
Die obige Fehlermeldung könnte nur durch einen sogenannten qualifizierten
Zugriff – d.h. unter Angabe des Namespaces – vermieden werden.
Durch die Einbinung von Namespaces mittels der Using-Anweisung läßt sich
folglich der Code etwas vereinfachen.
- Seite 36 -
.NET-Framework & C#.NET
3 .NET-Entwicklungsumgebung
3.1 Grundlagen des .NET-Framework
Die .NET-Welt besteht - wie bereits mehrfach erläutert -aus den beiden Komponenten:
 NET-Framework (Rahmenstruktur, welche Klassen usw. bereitstellt)
 Entwicklungsumgebung Visual Studio (hier programmieren wir)
3.1.1 Komponenten des .NET-Framework
Struktur des .NET-Frameworks
 1. Komponente
Klassenbibliothek - kurz FCL.
 2. Komponente
Common Type System - kurz CTS.
 Unter .Net ist das Typ-System für alle Propgrammiersprachen identisch.
 Da Typen früher nur in der Programmiersprache implemnetiert waren
und unter .Net in der FCL zu finden sind, gbit es unter .Net die Besonderheit, dass Typen sowohl über das entsprechende Schlüssenwort als
auch über die "Klasse" der FCL deklariert werden können.
 3. Komponente
Common Languge Specifikation - kurz CLS
- Seite 37 -
.NET-Framework & C#.NET
3.1.2 Kompilierungsphilosophie des .NET-Framework
Die Bezeichnung des Microsoft Entwicklungswerkzeuges als .Net Entwicklungsumgebung leitet sich aus der Philosophie zur Verteilung von Anwendungen, die heute üblicher Weise über des Netz erfolgt, ab.
Jeder Quell-Code ist erst lauffähig, wenn er in die Maschinensprache des ZielRechners, auf dem das Programm laufen soll, kompiliert worden ist. Da man
aber bei verteilten Anwendungen die technischen Voraussetzungen der Zielrechner häufig nicht kennt, ist diese Anforderung sehr hinderlich.
Unter .Net wird daieses Problem durch eine zweistufige Kompilierung gelöst.
Die erste Stufe wird IL-Code, IL für Intermediate Language - also Zwischen
Code, bezeichnet. Die zweite Stufe ist dann der native Code des Zielrechners.
IL-Code
Der .NET-Compiler erzeugt den maschinenunabhängigen IL-Code, der von
der Entwicklungsumgebung als EXE-Datei erzeugt und in dem Debug-Verzeichnis abgelegt.
Nativer Code <=> Common Language Runtime
Die endgültige Übersetzung des IL-Codes in die Maschinensprache des
Zielrechners erfolgt durch ein Übersetzungsprogramm auf dem Zielrechner.
Dieses Programm wird als Common Language Runtime Umgebung – kurz
CLR – bezeichnet.
- Seite 38 -
.NET-Framework & C#.NET
3.1.3 Zusammenfassung
Die folgende Grfaik fasst noch einmal die .Net-Struktur und den Kompilierungsvorgang zusammen.
- Seite 39 -
.NET-Framework & C#.NET
3.1.4 Veröffentlichung von Anwendungen
Soll ein Programm an anderer User weiter gegeben, d.h. veröffentlicht werden,
reicht es nicht, die exe-Datei mit dem IL-Code zu verteilen, da man nicht sicher sein, dass auf dem Zielrechner alle benötigten DLLs – sprich alle notwendigen Klassen - vorhanden sind. Will man dieses sicherstellen, muss der Weg
über die Veröffentlichung von Projekten gegangen werden. Hierbei werden
dann alle wichtigen Bibliotheken zusammengestellt und eine Setup-Datei zur
automatischen Installation erzeugt.
Beim Veröffentlichen von Projekten werden beispielhaft die nachstehenden
Dateien erzeugt, die z.B. auf eine CD kopiert werden können. Durch Aufruf der
SETUP-Datei werden dann nicht nur die Anwendung auf dem Zielrechner sondern auch die notwendigen und nicht vorhandenen DDLs installiert.
- Seite 40 -
.NET-Framework & C#.NET
3.2 Die IDE - Visual Studio .NET
Die .NET-Welt besteht - wie bereits mehrfach erläutert - aus den beiden Komponenten:
 .NET-Framework (Rahmenstruktur, welche Klassen usw. bereitstellt)
 Entwicklungsumgebung Visual Studio (hier programmieren wir)
Mit der FCL (Klassenbibliothek) haben wir uns in den vorherigen Kapiteln
schon ausführlich beschäftigt. Jetzt steht die IDE - die Entwicklungsumgebung
in Visual Studio - im Fokus.
Im Gegensatz zur Umgebung .NET ist C# unsere Sprache! Sie funktioniert
auch unabhängig von Viusal Studio in alternativen Entwicklungsumgebungen.
Ggf. kann das auch ein vollkommen unkomfortabler Editor sein. Der Quellcode
muss nur mittels des .NET-Compilers übersetzt werden.
3.2.1 Visual Studio und alternative Entwicklungsumgebungen
Visual Studio .NET
VS.Net ist die offizielle Entwicklungsumgebung von Microsoft. Hochschulen,
die am MSDN AA - Programm von Microsoft teilnehmen, können die VS.Net
Software kostenlos an ihre Studenten abgeben. Das ist bei der FHW der Fall.
Sie bekommen mit der Einschreibung einen Download-Link wo Sie sich die
IDE herunter laden können.
Shareware
Neben der VS.Net kann eine Anwendung auch mit einem einfachen Editor oder einem Shareware-Programm entwickelt werden. Bei den meisten Shareware-Programmen sind aber Einschränkungen gegenüber der Microsoft-Version gegeben.
Die folgenden Websites stellen ein gutes Portal für .NET-Entwickler dar. Dort
sind auch Links zu Shareware-Anbietern zu finden.
 http://www.it-visions.de/
 http://www.dotnetframework.de
- Seite 41 -
.NET-Framework & C#.NET
3.2.2 Aufruf der Entwicklungsumgebung (IDE) in Visual Studio
Den Vorgang beim Starten der IDE haben wir schon mehrfach beschrieben
und im Video veranschaulicht. Hier noch einmal im Überblick (Onepager für
die praktische Arbeit) die wichtigen Fakten zusammen:
Startfenster
Parameter der Projekt-Erstellung
 Vorlage
Einstellung der Sprachumgebung für die Entwicklung (C#)
Einstellung des Projekttyps (Konsole, Windows-Anwendung,...)
 Name
Name des Projektes (auf jeden Fall zu Beginn einstellen)
 Ort (Speicherort)
Dateiverzeichnis für das Root-Sammelverzeichnis des Projektes
- Seite 42 -
.NET-Framework & C#.NET
3.2.3 Speichern & Portieren von Projekten
Datei-Struktur
Die nachstehende Abbildung zeigt die Datei-Struktur, die Visual Studio bei
einem Konsolen-Projekt anlegt.
 Diese darf nicht verändert werden, da damit die projektinternen Verweise
nicht mehr gültig wären.
 Ausschließlich der Bezeichner des Root-Verzeichnisses des Projektes
auf der obersten Ebene - hier „1_HeWo_Konsole“ - darf geändert werden.
Kopieren von Projekten
Immer den obersten Ordner des Projektes mit allen Unterverzeichnissen kopieren.
Speichern
 Beim Speichern eines Projektes grundsätzlich immer das gesamte das
Projekt gespeichern.
 Nicht mit Hilfe von „Speichern unter“ Projekte portieren.
Portieren von Projekten
Projekte müssen ggf. von der Hochschule zu anderen Standorten portiert
werden. Die von anderen Office-Anwendungen bekannte Vorgehensweise
ist die, dieses über die Option „Speichern unter …“ des Datei-Menüs zu
realisieren. Hiervon ist bei Visual Studio Projekte dringend abzuraten, da
über diesen Weg immer nur Teile des Projektes auf dem neuen Datenträger
gespeichert werden.
Gehen Sie daher bitte immer den oben bereits beschriebenen Weg des Kopierens - in diesem Fall des Kopierens auf einen anderen Datenträger. Beachten Sie, dass Sie immer das gesamte Projekt kopieren, also die oberste
Verzeichnisebene im Zugriff haben.
- Seite 43 -
.NET-Framework & C#.NET
3.2.4 Komponenten der IDE
Hier werden noch einmal zusammenfassend und als Hilfe bzw. Überblick die
für den Einstieg wichtigsten Ansichten der IDE dargestellt. Erläutert wurden
Sie großenteils bereits.
Standard-Einstellung bei Konsolen-Anwendungen
Standard-Einstellung bei Windows-Anwendungen
 Designer-Ansicht
 Code-Ansicht
Die Code-Ansicht eines Windows-Projektes bedarf keiner weiteren Erläuterung – sie ist identisch mit der Ansicht bei Konsolen-Anwendungen.
- Seite 44 -
.NET-Framework & C#.NET
3.2.5 Generelle Einstellungen für die IDE
Die Ansicht der IDE kann individuell über das Menü Ansicht eingestellt werden. Das Ansichten Menü ist nachstehend abgebildet. Hinter den Menü-Items
stehen entsprechenden Tastaturkombinationen.
- Seite 45 -
.NET-Framework & C#.NET
3.3 C#-Programmierung in Visual Studio .NET
3.3.1 Anweisungen & Blöcke
Optische Differenzierungen in Visual Studio
Durch den Compiler werden bereits einige optische Differenzierungen vorgenommen. So werden beispielsweise Schlüsselworte in der Farbe dunkelblau
und Klassen der Farbe hellblau dargestellt. Eine Übersicht gibt die nachstehende Auflistung.
 Schlüsselwort: Dunkelblau class
 Klasse: Hellblau Program
 Bezeichner: Schwarz faktor1
 Kommentar: Grün //Deklarationen
Blöcke { }
Anweisungen
 Anweisungsende ;
 jede Programmanweisung endet mit einem Semikolon
 möglichst eine Anweisung je Zeile
 eine Anweisung kann über mehrere Zeilen gehen
 bei Fortsetzungszeilen, wenn nicht automatisch eingezogen, einziehen
der Folgezeile um einen Tabstopp (vier Leerzeichen)
 zwischen Methoden- und Eigenschaftendefinitionen mindestens eine
Leerzeile einfügen
 grundsätzlich die Standardeinstellung des Code-Editors verwenden
(intelligente Einzüge, Einzüge um vier Zeichen, als Leerzeichen gespeicherte Tabstopps).
- Seite 46 -
.NET-Framework & C#.NET
3.3.2 Kommentare
Kommentare haben keine Auswirkung auf den Programmcode. Sie dienen
ausschließlich der Erläuterung für den Entwickler. Hilfreich ist dieses wenn
man nach einiger Zeit den Code noch einmal überarbeiten muss. Die Kommentare helfen einem dann die der Programmierung zu Grunde liegende Logik wieder zu erinnern.
Die Kommentierung von Code kann aber bei der Entwicklung auch anders eingesetzt werden. Durch eine Auskommentierung von Code wird dieser deaktiviert und es kann die Funktionsweise des Programms ohne diese Codezeilen
getestet werden.
- Seite 47 -
.NET-Framework & C#.NET
3.3.3 Konventionen für Bezeichner
Bezeichner verwendet man, um selbst erstellten Komponenten wie Variablen,
Klassen usw. einen Namen zu geben.
 nur wenig formale Regeln.
 einheitliche Konventionen wichtig
 Übersichtlichkeit des Programms
 Bearbeitung durch mehrere Personen
 wichtige formale Regel: Differenzierung von Groß- und Kleinschreibung
(test <> Test)
 Zulässig sind: Buchstaben, Ziffern, Unterstrich
 Unzulässig:
 alle anderen Zeichen
 auch Leerzeichen
 Bezeichner darf nicht identisch mit Schlüselwort sein
 Bezeichner darf nicht mit einer Ziffer beginnen
 Bei den Bezeichnern ist unter. NET die CamelCase-Notation üblich.
Alternative Konventionen
 Namenskonventionen sind Festlegungen für die Schreibweise der Bezeichner. Sie sollen die Lesbarkeit des Codes verbessern.
 Konventionen können prinzipiell beliebig sein. Es haben sich aber die folgenden Konventionen als Standards entwickelt.
 Ungarische Notation
 Kodierung des Typs im Namen: intZaehler (Typ Integer)
 Kodierung der Verwendung im Namen: qryKunden (Query/Abfrage)
 Unterstrich Konvention
 Verwendung von Unterstrichen: kunden_nummer
 CamelCase Konvention
 lowerCamelCase (CamelCase): kundenNummer
 UpperCamelCase (PascalCase): KundenNummer
- Seite 48 -
.NET-Framework & C#.NET
3.3.4 Änderung von Bezeichnern
Werden Bezeichner geändert, wird diese Änderung nicht automatisch im gesamten Code nachvollzogen – was auch so sein muss. Dennoch stellt VS.Net
eine Hilfe zum Umbenennen von Bezeichner zur Verfügung.
wird das Fenster zum Umbenennen aktiviert
Nach dem Umbenennen der Variablen kann der gesamte Code nach dem alten Bezeichner durchsucht und entsprechend ersetzt werden
- Seite 49 -
.NET-Framework & C#.NET
3.3.5 Anatomie von C#-Anwendungen
In diesem Abschnitt soll der Aufbau, die Anatomie, von Konsolen- und
Windows-Anwendungen erläutert werden.
Als Referenz sei eingangs noch einmal auf die bereits bekannte hierarchische
Struktur von Namespace, Klasse und Methode hingewiesen. Diese Struktur ist
auch bei den Anwendungstypen unter .Net wiederzufinden.
- Seite 50 -
.NET-Framework & C#.NET
3.3.5.1Konsolen-Anwendungen
Struktur einer Konsolen-Anwendung
Die Struktur von Konsolen-Anwendungen ist, wie bereits oben erwähnt, sehr
übersichtlich. Diese Anwendung besteht hierarchisch gesehen aus einem
Namespace, einer Klasse und einer Methode.
Eintrittspunkt (Entry-Point) Main-Methode
Jedes Programm muss einen eindeutigen Eintrittspunkt. (Entry-Point) haben.
Die Eindeutigkeit muss gegeben sein, damit der Compiler weiß, an welcher
Stelle das Programm beginnt. Bei .Net-Programmen ist dieser Eintrittspunkt
die Main-Methode. Jedes Programm muss daher diese Main-Methode besitzen und diese darf auch nicht umbenannt werden.
 Jedes Projekt muss eine Main-Methode als Startpunkt haben.
 Die Main-Methode stellt den Startpunkt jeder Applikation dar.
 Der Bezeichner „Main“ darf nicht geändert werden.
- Seite 51 -
.NET-Framework & C#.NET
3.3.5.2Windows-Anwendungen
Ablauflogik beim Aufruf
Die nachstrehende Grafik veranschaulicht die Struktur. Ausgangspunkt ist, wie
bei allen .Net-Anwendungen, die Main-Methode. In derr Main-Methode wird
die Instanz der Form erzeugt, was mittels des Konstruktors der Form erfolgt.
Aus dem Konstruktor heraus erfolgt dann der Aufruf der InitializeComponentMethode, die die Objekte der Form erzeugt.
Nachstehend die Dateien im Projektexplorer.
- Seite 52 -
.NET-Framework & C#.NET
Form1.Designer.cs
- Seite 53 -
.NET-Framework & C#.NET
Form1.cs
Program.cs
- Seite 54 -
.NET-Framework & C#.NET
3.3.6 Debug-Fenster
Das Debugging unter Visual Studio hat im Grunde zwei Zielrichtungen.
 Zum einen kann man ein Programm Schritt für Schritt durchführen lassen
und dabei anhand des Codes überprüfen, ob die Logik des Programmablaufs korrekt ist.
 Zum anderen hat man während Prozesses die Möglichkeit, sich den Inhalt der Variablen anzeigen zu lassen.
3.3.6.1Vorgehensweisen
Einzelschrittmodus
Durch den sogenannten Einzelschrittmodus wird ein Programm gestartet
und mittels der <F11>-Taste Anweisung für Anweisung abgearbeitet.
Break-Points
Break-Points können durch Klicken auf die graue Leiste (linksseitig vom
Code) gesetzt bzw. gelöscht werden. Das programm kann mit der >f5>Taste gestartet werden und toppt dann beim Break-Point.
- Seite 55 -
.NET-Framework & C#.NET
3.3.6.2Debug-Ansichten
Befindet sich das Programm im Debug-Modus, kann z.B. über das Menü Debuggen -> Fenster das Lokal-Fenster aktiviert werden, welches die Werte der
lokalen Variablen zeigt. Möglicherweise ist dies auch bereits automatisch aktiviert.
- Seite 56 -
.NET-Framework & C#.NET
3.3.6.3Anzeigen von Variablenwerte
Debug-Modus mit Lokal-Fenster
Sensitive Hilfe
- Seite 57 -
.NET-Framework & C#.NET
3.3.7 Projektmappen-Explorer & Symbole
Projektexplorer
Der Projektexplorer stellt die Dateistruktur des Projektes dar, d.h. aus welchen
Dateien das Projekt besteht. Zusätzlich werden z.B. unter dem Knoten Verweise die eingebundenen Namespace-Bibliotheken aufgeführt.
 Auf der obersten Ebene ist das Gesamtprojekt angeordnet.
 Darunter befinden sich gleichrangig
 die Verweise
 die Form1.cs mit
 der Form1.Designer.cs und
 der Form1 (mit dem Ergnis-Methoden der Form!)
 die Program.cs (Formübergreifender Code)
- Seite 58 -
.NET-Framework & C#.NET
Übersicht zentraler Symbole
Symbol
Beschreibung
Symbol
Beschreibung
Namespace (Namensraum)
Methode() oder Funktion
Klasse
Operator
Schnittstelle
Eigenschaft
Struktur
Feld oder Variable
Union
Ereignis [Event]
Enum
Konstante
TypeDef
Enumerationselement
Modul
Zuordnungselement
Erweiterungsmethode
Externe Deklaration
Delegate
Fehler
Ausnahme
Vorlage
Zuordnung
Unbekannt
Typweiterleitung
Additive Signalsymbole
Symbol
Beschreibung
Public. Der Zugriff ist von jeder Position innerhalb dieser
<Kein SigKomponente und von jeder Komponente, die darauf vernalsymbol>
weist, möglich.
Protected. Der Zugriff ist von der enthaltenden Klasse oder
dem enthaltenden Typ oder von abgeleiteten Klassen oder
Typen möglich.
Private. Der Zugriff ist nur innerhalb der enthaltenden Klasse oder des enthaltenden Typs möglich.
Versiegelt.
Freund/intern. Der Zugriff ist nur über das Projekt möglich.
Shortcut. Eine Verknüpfung zum Objekt.
- Seite 59 -
.NET-Framework & C#.NET
B. Programmiersprache Visual C#
4 Exkurs: Klassen für die Konsolen-Programmierung
4.1 Console-Klasse
Die Klasse Console beinhaltet eine Reihe statischer Methoden zur Ein- und
Ausgabe auf der Konsole.
ReadLine()
Einlesen der Eingaben aus dem Tastaturpuffer:
faktor1 = Console.ReadLine();
WriteLine()
Ausgabe des Textes in " " sowie Zeilenvorschub:
Console.WriteLine("Multiplikation zweier Zahlen");
Ausgabe des Textes in " " ohne Zeilenvorschub:
Console.Write("Multiplikation zweier Zahlen");
4.2 Convert-Klasse
Diese Klasse stellt statische Methoden zur Konvertierung von Daten zur Verfügung.
Z.B. Konvertieren Eingabe aus dem Tastaturpuffer in einen Double-Typ:
faktor1 = Convert.ToDouble(Console.ReadLine());
- Seite 60 -
.NET-Framework & C#.NET
4.3 Formatierung von Ausgaben
Beispiel
Benutzerdefinierte Zahlenformatierung
Die benutzerdefinierte Formatierung ist eine Alternative und erfolgt innerhalb
der WriteLine-Methode. Die Grundstruktur sieht dabei wie folgt aus
Console.WriteLine ("{0,10:#,##0.00}", Endwert);
 Der erste Teil der Anweisung "{0,10:#,##0.00}" ist der Formatierungsstring.
 Die erste Zahl – hier die 0 – gibt den Platzhalter für die später folgende
Variable an. Die Ziffern werden von 0 aufsteigend nummeriert, wobei
die 0 der ersten Variablen, die 1 der zweiten Variablen usw. zugeordnet werden.
 Die zweite Zahl – hier die 10 – gibt an, wie viel Stellen für die Ausgabe
reserviert werden sollen. Die ersten beiden Parameter werden durch
ein Komma getrennt.
 Nach dem Doppelpunkt erfolgt die Ausgabeformatierung. Das # ist ein
Platzhalter für eine beliebige Ziffer. Diese wird unterdrückt, sofern es
sich um eine führende Null oder um eine Null nach dem Dezimalkomma handelt. Der Platzhalter 0 steht auch für eine Ziffer, wobei eine
führende Null bzw. eine Null nach dem Komma ausgedruckt wird.
 Der zweite Teil der Anweisung Endwert stellt die Liste der Variablen
dar. Sie werden entsprechend der Reihenfolge den Platzhaltern 0, 1
usw. zugeordnet.
- Seite 61 -
.NET-Framework & C#.NET
Formatierungsbeispiele
 Screenshot
 Code
- Seite 62 -
.NET-Framework & C#.NET
 Erläuterung
 In der Zeile 35 erfolgt die unformatierte Ausgabe. Man erkennt auf dem
Bildschirm dass der Wert 3000 direkt ohne Tausender-Trennung ohne
Nachkommastellen ausgegeben wird.
 In der Zeile 39 erfolgt eine einfache Formatierung. Der Formatierungstring "Produkt : {0,10:N}" ist der erste Teil der Anweisung. Hier wird der
Text “Produkt :“ ausgegeben, gefolgt von einem Platzhalter. Der Platzhalter steht immer in geschweiften Klammern innerhalb des Formatierungstrings. Die erste Zahl legt fest, welche Variable aus der Liste nach dem
Formatierungsstring ausgegeben werden soll. Die zweite Zahl 10 legt fest
wie viel Stellen für die Ausgabe reserviert werden. Als letztes wird durch
einen Doppelpunkt getrennt das Format festgelegt. Die Angabe von N
legt ein Standardformat fest, dass Zahlen mit Tausender-Trennung und
zwei Nachkommastellen ausgibt.
 In der Zeile 43 ist die Standardformatierung N ersetzt worden durch
"#,##0.0000". Dieses ist eine selbst konstruierte Formatierung.
 Mit Hilfe der Platzhalter # und 0 können beliebige Formatierungen aufgebaut werden.
 Wichtig ist noch, dass in der amerikanischen Schreibweise dieTausender-Trennung das Komma und die Dezimalt-Tennung der Punkt ist.
 Das # ist der Platzhalter für eine beliebige Ziffer, der aber führende und
nachstehende Nullen ignoriert. Ein Beispiel soll dieses noch einmal
veranschaulichen. Soll die Zahl 10 ausgegeben werden, soll auch nur
die Zahl 10 und nicht 0.010 auf der Konsole erscheinen. Demgegenüber ist die 0 ein Platzhalter, der führende nachstehende Nullen ausgibt. In diesem Beispiel sind eine Nul vor dem Komma und vier Nachkommastellen mit Nullen verbindlich.
 In der Zeile 47 erfolgt die Ausgabe mehrerer Werte mithilfe des Standardformats. Zu erkennen ist, dass bei dem ersten Platzhalter erste Zahl eine
0 und bei dem zweiten Platzhalter erste Zahl eine 1 ist. Wie bereits beschrieben, weist die 0 auf den ersten Wert in der nachstehenden Liste,
also faktor1. Demzufolge verweist die 1 im zweiten Platzhalter auf die Variable faktor2 und die zwei auf die Variable produkt.
- Seite 63 -
.NET-Framework & C#.NET
5 Datentypen I
Einordnung
 Programmiersprache
 .Net-Framework
Begründung für unterschiedliche Datentyp
Anhand der C#-Referenz erkennt man, dass eine Vielzahl von Datentypen
existieren. Hier eine kurze Begründung für deren Notwendigkeit.
 Speicherung unterschiedlicher Informationen:
 Zahlen
 Texte (Ziechenkette = String)
 Differnzierung numerischer Datentypen:
 unterschiedlichen Speicherbedarf
- Seite 64 -
.NET-Framework & C#.NET
5.1 Typen - Common Type System vs. Programmiersprache
Typen in der .NET-Klassenbibliothek
Typen in der Programmiersprache
Grundsatz: Verwendung des Schlüsselwortes
- Seite 65 -
.NET-Framework & C#.NET
5.2 Differenzierung der Datentypen
5.2.1 Differenzierung der Typen


Werttypen
primitive Datentypen; (Deklaration ohne Aufruf des Konstrukturs new)
Verweistypen
Referenztypen
- Seite 66 -
.NET-Framework & C#.NET
5.2.2 Werttpyen
Strukturen
Enumerationen
- Seite 67 -
.NET-Framework & C#.NET
5.3 Datentypen in C#
Numerische Typen
Bool'sche Typen
Alphanumerische Typen
- Seite 68 -
.NET-Framework & C#.NET
Wertebereich von Datentypen
 Ganzzahlige Typen
 Gleitkommatpyen
- Seite 69 -
.NET-Framework & C#.NET
5.4 Methoden von Datentypen
Da unter .Net die Datentypen in der Klassenbibliothek implementiert sind verfügen sie im Gegensatz zu anderen Programmiersprachen über Methoden.
Methoden des Typs String
 Die Methode Concat ist eine statische Methode, was an dem roten S in
der ersten Spalte erkennbar ist. Diese Methode kann also nur in Verbindung mit der Klasse String verwendet werden.
 Die Methode ToUpper ist hingegen eine Instanzmethode und kann daher
nur mit der Instanz verwendet werden.
- Seite 70 -
.NET-Framework & C#.NET
Beispiel
Bei dem folgenden Beispiel sollen zwei in Kleinschreibweise eingegebene
Texte in Großschreibweise umgewandelt und verbunden werden.
Die Umwandlung erfolgt mit der Methode ToUpper, die Verkettung der beiden
Texte mittels der Methode Concat.
- Seite 71 -
.NET-Framework & C#.NET
Die beiden nachstehenden Abbildungen zeigen noch einmal den Unterschied
zwischen statischen und Instanz-Methoden.
 Instanz-Methoden
Verwendet man den Bezeichner text1 der Instanz, also die Instanz, stehen
auch nur die Instanzmethoden zur Verfügung. Da die Methode ToUpper
eine Instanzmethode ist, wird sie hier aufgelistet. Die statische Methode
concate steht hier nicht zur Verfügung.
 Statische Methoden
Verwendet man umgekehrt anstatt des Bezeichners der Instanz die zu
Grunde liegende Klasse string, so werden die statischen Methoden zur Verfügung gestellt. Die Methode ToUpper ist hier nicht zu finden.
- Seite 72 -
.NET-Framework & C#.NET
5.5 Literale
Beispiele
Numerisches Literal
faktor1 = 123,45
Alphanumerisches Literal
text1 = "Informatik ist toll!"
Literale für Zeichenketten (String)
 Reguläres String-Literal
text1 = "Informatik ist toll!!!";
 String-Literal mit Anführungszeichen
text2 = "Informatik ist \"toll\"!!!";
Literale für boolsche Werte
bnLogik = true;
Literale für numerische Werte
 Grundsätzliche ist die Zuweisung von numerischen Literalen sehr einfach:
zahl1 = 75;
 In einer Vielzahl von Fällen gibt es bei der Zuweisung von Literalen keine
Probleme, da die numerischen Literale implizit konvertiert werden. So
kann z.B. ein ganzzahliger Wert bei der Zuweisung zu einer Variablen
vom Typ Double ohne Schwierigkeiten umgewandelt werden.
 Die Zuweisung numerischer Literale kann dann zu Schwierigkeiten führen, wenn der Definitionsbereichs bei ganzzahligen Variablen und nichtnegativen Variablen zu beachten ist. Die anderen Suffixe sind der nachstehenden Abbildung zu entnehmen.
- Seite 73 -
.NET-Framework & C#.NET
5.6 Variablen und Konstanten
Deklaration von Variablen
Eine Variable ist ein über einen Namen ansprechbarer, termporrärer Speicherplatz im Hauptspeicher.
int i, test1;
Zu beachten sind die in Abschnitt „3.3.3 Konventionen für Bezeichner“ festgelegten Konventionen.
Initialisierung von Variablen
Durch die obige Anweisung werden Variablen deklariert nicht aber in initialisiert. D.h., dass der Variable kein Initial-Wert zugewiesen wird. Erfolgt dieses auch nicht im weiteren Programm-Verlauf kann es z.B. bei der Ausgabe
zu dem nachstehenden Fehler kommen.
Gültigkeit von Variablen
Eine Variable ist nur in dem durch { } markierten Block einschließlich der untergeordneten Blöcke gültig.
- Seite 74 -
.NET-Framework & C#.NET
Kostante
Der Verwendung von Konstanten ist - wie der Name schon besagt - eingeschränkt. Der Inhalt einer Konstanten ist konstant und kann nicht verändert
werden. So könnte bspw. die Verwendung einer Konstanten für den MWStSatz in einem Programm sinnvoll sein.wenn man davon ausgeht, dass dieser Steuer-Satz nicht geändert wird und innerhalb des Programmes vor einem versehentlichen Überschreiben gesichert werden soll.
Die Deklaration von Konstanten erfolgt durch analog zu Variablen jedoch
unter der zusätzlichen Verwendung des Schlüsselwortes const:
const int Konstante = 100;
Beim Versuch des Überschreibens tritt der folgende Fehler auf.
- Seite 75 -
.NET-Framework & C#.NET
5.7 Operatoren und Ausdrücke
Beispiel
In der folgenden Anweisung
produkt = a * b;
in dieser Programmzeile sind folgende Elemente enthalten:
 Operator
: Multiplikationszeichen „ * “
 Ausdruck
: „a * b“
 Zuweisungsoperator : Gleichheitszeichen „ = “
Zuweisungsoperatoren
Das „ = “ wird als Zuweisungsoperator bezeichnet.
 Es gilt immer:
Ziel = Quelle;
 Der Zuweisungsoperator ist kein mathematisches Gleichheitszeichen.
Ein Vertauschen der Seiten zu "Quelle = Ziel" ist nicht zulässig.
 Der Wert des rechts stehenden Ausdrucks wird der links stehenden Variablen zugewiesen
 Auf beiden Seiten des Zuweisungsoperators müssen Ausdrücke des gleichen Datentyps stehen (s. auch Typ-Konvertierung)
Weitere Zuweisungsoperatoren
Operatoren
=
+=
-=
*=
/=
%=
&=
|=
^=
<<=
>>=
??
Operatoren für die Grundrechenarten
- Seite 76 -
.NET-Framework & C#.NET
Verkürzte Zuweisung
Verkürzte Zuweisungen sind eine Kombination des Zuweisungsoperators
mit einem Rechenoperator. Die folgende Anweisung
i = i + 3;
wird dadurch auf diese Schreibweise verkürzt
i += 3;
Die nachstehenden Darstellungen sind der Publikation aus dem Herdt-Verlag entnommen
Inkrementierung und Dekrementierung
Logische Vergleichsoperatoren
- Seite 77 -
.NET-Framework & C#.NET
Verknüfungsoperatoren
- Seite 78 -
.NET-Framework & C#.NET
5.8 Konvertierung von Datentypen
Die Konvertierung von Datentypen ist ein zentraler und wichtiger Aspekt der
Programmierung. Grundsätzlich gilt, dass auf beiden Seiten des Zuweisungsoperator die gleichen Typen stehen müssen.
Ziel = Quelle,
Grundsätzlich muss bei unterschiedlichen Datentypen immer konvertiert werden. Es gibt aber eine Ausnahme. Ist der Quelldatentyp eine Untermenge des
Zieldatentyps, kann auf eine explizite Konvertierung verzichtet werden. In diesem Fall erfolgt die Konvertierung implizit vom Compiler. Ein Beispiel soll dieses noch mal veranschaulichen. Sei die Variable zahl2 vom Typ Integer und
die Variable zahl1 vom Typ double. Dann ist die folgende Anweisung trotz unterschiedlicher Datentypen auf beiden Seiten der Zuweisung korrekt, da der
Wertebereich des Typs integer eine Untermenge des Typs double ist.
zahl1 = zahl2 (double = interger)
Es wird also in der Programmierung zwischen den beiden folgenden Konvertierungsoptionen unterschieden:
 implizite Konvertierung
 explizite Konvertierung
Implizite Konvertierungen
- Seite 79 -
.NET-Framework & C#.NET
Explizite Konvertierung
Bei der expliziten Type-Konvertierung stehen verschiedene Vorgehensweisen
zur Verfügung.
 Explizite Konvertierung durch Zuweisung mit Type-Angabe
 Explizite Konvertierung durch Methoden der Typ-Strukturen
 Explizite Konvertierung durch Methoden der Convert-Klasse
 Verwendung der Type-Angabe bei der Zuweisung
Diese Vorgehensweise ist sehr komfortabel, da der Zieldatentyp nur in
Klammern für den Ausdruck auf der rechten Seite des Zuweisungsoperators
eingefügt werden muss.
Zahl1 = (Double) Console.ReadLine();
Leider hat diese Vorgehensweise nicht immer einsetzbar. Wir werden sie
sehr intensiv bei der Programmierung von Excel Anwendungen einsetzen
 Methoden der Typ-Strukturen
Des Weiteren stehen die Konvertierungs-Methoden der Datentypen zur Verfügung, wie z.B. die des nachstehenden Typs Decimal.
 Methoden der Convert-Klasse
- Seite 80 -
.NET-Framework & C#.NET
6 C#-Anweisungen
Einordnung in das .Net-Framework
Einordnung in die Programmiersprache C#
- Seite 81 -
.NET-Framework & C#.NET
6.1 Vom Problem zum Programm
Grundsätzliche Vorgehensweise
Die grundsätzliche Vorgehensweise bei der Erstellung eines Programms erfolgt in drei Schritten:
 Problemanalyse
 Struktogramm
 Codierung
Strukturelemente
Um die Logik von Sachverhalten darzustellen gibt es im Wesentlichen nur
drei Elemente:
 Sequenz
 Alternation
 IIteration
Eine Sequenz sind einfach mehrere Anweisungen, die nacheinander abgearbeitet werden. Eine Alternation ist eine Entscheidung zwischen Alternativen und Iteration eine Wiederholung oder auch Schleife.
Betrachtet man einmal alle im Leben oder einem Betrieb auftretende Prozesse, so lassen sich diese immer durch diese drei Strukturelemente darstellen.
- Seite 82 -
.NET-Framework & C#.NET
6.1.1 Beispiel für Vorgehensweise
Grundsätzliche Vorgehensweise
Die grundsätzliche Vorgehensweise bei der Erstellung eines Programms erfolgt in drei Schritten:
 Problemanalyse
 Struktorgramm
 Codierung
Problemstellung
Nach Eingabe der Daten für Anfangskapital, Laufzeit und Zinssatz sollen die
Berechnungen durchgeführt und Tabelle ausgegeben werden. Zu beachten ist
dabei noch, dass ab dem 5. Jahr ein Bonus von 2% auf Zinsatz gewährt wird.
- Seite 83 -
.NET-Framework & C#.NET
6.1.1.1Problemanalyse
Zu Beginn der Analyse sollten die Berechnungen einmal manuell durchgeführt
werden, damit der Rechenweg, also das was programmiert soll, festgelegt ist.
Die nachstehende Abbildung zeigt dieses.
 Vor der Berechnung wird gepürft, ob das akutelle Jahr kleiner oder gleich
5 ist.
 Danach erfolgt die Berechnung der Zinsen
zinsen = 1.000 * 3 / 100 = 30.
 Abschließend wird das Endkapital berechnung:
endkapital = 1.000 + 30 = 1.030
Ab dem 5. Jahr wird der Zinssatz um 2 erhöht; die Berechnungen sind identisch.
- Seite 84 -
.NET-Framework & C#.NET
Um das Ganze in einer strukturierten Form darzustellen sind noch weitere Vorarbeiten notwendig. Als Vorstufe sind die obigen Berechnungen nachstehend
mit Variablen-Bezeichnern versehen worden.
 Aus der Überprüfung 1<=5 wird jetzt
aktuellesJahr <= laufZeit
 Bei den Berechnungen ergibt sich jetzt
zinsen = anfangsKapital * zinsSatz / 100
bzw. endKapital = anfangsKapital + zinsen
 Iteration
Im Prinzip dürfte bereits deutlich geworden sein, dass diese Berechnungen
entsprechend der Laufzeit wiederholt werden, es sich folglich um eine
Schleife - auch Iteration - handelt.
- Seite 85 -
.NET-Framework & C#.NET
Allerdings haben wir noch Probleme mit dem Inhalt der Schleife, dem
Schleifenkörper:
 Die Berechnungen im ersten Jahr lauten:
zinsen = anfangsKapital * zinsSatz / 100
endKapital = anfangsKapital + zinsen
 Die Berechnungen im zweiten Jahr lauten:
zinsen = endKapital * zinsSatz / 100
endKapital = endKapital + zinsen
Im Grunde sind diese Berechnungen identisch, können aber so noch
nicht vereinheitlicht werden, da im ersten Jahr mit der Variablen anfangsKapital und im zweiten Jahr mit der Variablen endKapial gerechnet werden muss. Würde man sich entscheiden nur mit den Anweisung des ersten Jahres zu arbeiten gibt es ab dem zweiten Jahr ein Problem; entscheidet man für die Anweisungen des zweiten Jahres gibt es im ersten
Jahr ein Problem. Dieser Konflikt lässt sich lösen, wenn man vor der
Schleife einmal die Anweisung
endKapital = anfangsKapital
einschiebt. Damit hat die Variable endKapital einen Startwert und es kann
in der Schleife immer die Logik des zweiten Jahres verwendet werden.
 Alternation
Ein weiteres Problem stellt die modifizierte Berechnung ab dem fünften Jahr
dar. In disem Fall wird der Zinssatz um 2% erhöht.
Diese Struktur wird als Alternation bezeichnet. Bei der Berechnung der Zinsen gibt es folglich abhängig von dem aktuellen Jahr eine unterschiedliche
Berechnung.
- Seite 86 -
.NET-Framework & C#.NET
6.1.1.2Struktogramm
Ein Struktogramm ist die komprimierte Darstellung der Logik eines Programms. Für Sequenzen, Alternationen und Iteration sind bestimmte Symbole
definiert. Das folgende Struktogramm entsteht eigneltich in mehreren Schritten; diesen Prozess können wir in einem Skript nicht darstellen. Es sei daher
auf das entsprechende Video verwiesen.
- Seite 87 -
.NET-Framework & C#.NET
6.1.1.3Codierung
Als Basis für die Programmierung dient jetzt das Struktogramm. Dieses vor
Augen kann jetzt Zeile für Zeile das Struktogramm in Code umgesetzt werden.
Dabei kann eine Sequenz des Struktogramms durchaus mehrere Zeilen im
Code umfassen. Die Eingabe bspw. geht von Zeile 17 bis zur Zeile 29.
- Seite 88 -
.NET-Framework & C#.NET
6.1.2 Grundsätzliches zur Problemanalyse
Die Anaylse ist die wichtigste Phase in der Entwicklung. Die Auseinandersetzung mit der Logik einer Problemstelung und deren Darstellung in kompakter,
grafischer Form ist elementar. Das Prinzip lautet dabei:
Reduktion des Schwierigkeitsgrades
PAP
NSD
Fazit
Das Struktogramm ist heute die wohl am häufigsten eingesetzt Darstellungsform. Dennoch scheint es in bei komplexen Ablaufstrukturen sinnvoll,
den PAP additiv zu verwenden.
- Seite 89 -
.NET-Framework & C#.NET
6.1.3 Kontrollstrukturen
Die nachstehende Abbildung stellt die Inhalte der folgenden Kapitel in grafischer Form dar. Wir werden diese Aspekte, beginnend mit den Verzweigungen, auch Alternationen, und darauf folgend den Schleifen, auch Iterationen,
bearbeiten.
- Seite 90 -
.NET-Framework & C#.NET
6.2 Kontrollstrukturen
Die nachstehende Abbildung stellt die Inhalte der folgenden Kapitel in grafischer Form dar. Wir werden diese Aspekte, beginnend mit den Verzweigungen, auch Alternationen, und darauf folgend den Schleifen, auch Iterationen,
bearbeiten.
6.2.1 Alternationen (Verzweigungen)
In dem nun folgenden Kapiteln werden die Verzweigungen, in der Grafik noch einmal deutlich gemacht, systematisch erläutert.
- Seite 91 -
.NET-Framework & C#.NET
6.2.1.1Einseitige Auswahl
Syntax
Die einseitige Alternation hat die folgende Syntax.
Beschreibung
Bedingung: ein oder mehrere Ausdrücke der beiden folgenden Arten:
 Ein numerischer Ausdruck oder ein Zeichenfolgenausdruck, der True oder False ergibt.
 Bei der Verknüpfung mehrerer Bedingungen können diese mit logischen
Operatoren verknüpft werden.
Enthält der if-Block nur eine Anweisung, kann auf die Blockung durch { } verzichtet werden.
NSD
Im NSD wird eine eineitige Alternation wie folgt dargestellt. Da nur das Symbol
für eine zweiseitige Alternation existiert, wird der nein-Block entwertet.
- Seite 92 -
.NET-Framework & C#.NET
Beispiel
Problemstellung
Zu erstellen ist ein C#-Programm, das anhand des Bruttoumsatzes den Rabatt
und den Nettoumsatz bestimmt. Dabei gelten folgende Bedingungen:
 bis 1000,- € Umsatz wird kein Rabatt gewährt
 ab 1000,- € Umsatz wird ein Rabatt von 10% gewährt
Screenshot
NSD
- Seite 93 -
.NET-Framework & C#.NET
Code
//Deklarationen double bruttoPreis, nettoPreis, rabatt; //Prozedur //Eingabe Console.WriteLine("Rabatt‐Berechnung"); Console.WriteLine("*****************"); Console.WriteLine(); Console.Write("Brutto‐Preis: "); bruttoPreis = Convert.ToDouble(Console.ReadLine()); //Berechnung rabatt = 0; if(bruttoPreis>=1000) { rabatt=bruttoPreis * 0.1; } nettoPreis = bruttoPreis ‐ rabatt; //Ausgabe Console.WriteLine(); Console.WriteLine("Brutto‐Preis : {0,12:N}", bruttoPreis); Console.WriteLine("Rabatt : {0,12:N}", rabatt); Console.WriteLine("Netto Preis : {0,12:N}", nettoPreis); Console.ReadLine();
- Seite 94 -
.NET-Framework & C#.NET
6.2.1.2Zweiseitige Auswahl
Syntax
Die zweiseitige Alternation hat die folgende Syntax.
Beschreibung
Bedingung: ein oder mehrere Ausdrücke der beiden folgenden Arten:
 Ein numerischer Ausdruck oder ein Zeichenfolgenausdruck, der True oder False ergibt.
 Bei der Verknüpfung mehrerer Bedingungen können diese mit logischen
Operatoren verknüpft werden.
Enthält der if- oder else-Block nur eine Anweisung, kann auf die Blockung
durch { } verzichtet werden.
NSD
Im NSD wird eine eineitige Alternation wie folgt dargestellt. Da nur das Symbol
für eine zweiseitige Alternation existiert, wird der nein-Block entwertet.
- Seite 95 -
.NET-Framework & C#.NET
Problemstellung
Zu erstellen ist ein C#-Programm, das anhand des Bruttoumsatzes den Rabatt
und den Nettoumsatz bestimmt. Dabei gelten folgende Bedingungen:
 bis 1000,- € Umsatz wird ein Rabatt von 10% gewährt
 ab 1000,- € Umsatz wird ein Rabatt von 20% gewährt
Screenshot
NSD
- Seite 96 -
.NET-Framework & C#.NET
Code
//Deklarationen double bruttoPreis, nettoPreis, rabatt; //Prozedur //Eingabe Console.WriteLine("Rabatt‐Berechnung"); Console.WriteLine("*****************"); Console.WriteLine(); Console.Write("Bruoot‐Preis: "); bruttoPreis = Convert.ToDouble(Console.ReadLine()); //Berechnung if (bruttoPreis < 1000) { rabatt = bruttoPreis * 0.1; } else { rabatt = bruttoPreis * 0.2; } nettoPreis = bruttoPreis ‐ rabatt; //Ausgabe Console.WriteLine(); Console.WriteLine("Brutto‐Preis : {0,12:N}", bruttoPreis); Console.WriteLine("Rabatt : {0,12:N}", rabatt); Console.WriteLine("Netto Preis : {0,12:N}", nettoPreis); Console.ReadLine();
- Seite 97 -
.NET-Framework & C#.NET
6.2.1.3Mehrseitige Auswahl
Syntax
Beschreibung
Der Selektor ist i.d.R. eine Variable, deren Wert bei den verschiedenen caseFällen abgeprüft wird. Führt eine case-Prüfung zu einer wahren Bedingung, so
werden die nach der case-Anweisung stehenden Anweisungen ausgeführt.
Zwei case-Anweisungen dürfen jedoch nicht denselben Wert aufweisen. Die
Ausführung des Anweisungstexts beginnt mit der ausgewählten Anweisung
und wird fortgesetzt, bis die break-Anweisung dem case-Text die Steuerung
entzieht. Nach jedem case-Block muss eine Sprunganweisung, wie break, stehen. Dies gilt auch für den letzten Block, unabhängig davon, ob er eine caseAnweisung oder eine default-Anweisung enthält.
NSD
- Seite 98 -
.NET-Framework & C#.NET
Problemstellung
Das Kindergeld beträgt in Deutschland gemäß § 66 Abs. 1 EStG für das erste,
zweite und dritte Kind jeweils 154,00 Euro monatlich und für das vierte und jedes weitere Kind 179,00 Euro monatlich (Stand: 20.12.2007). Das nachfolgende Programm soll in Abhängigkeit von der Kinderzahl die monatliche bzw.
jährliche Kindergeldzahlung berechnen.
Screenshot
NSD
- Seite 99 -
.NET-Framework & C#.NET
Code
//Dekalrationen Double kinderGeld, kinderGeldJahr; Int16 anzahlKinder; //Prozedur //Eingabe Console.Clear(); Console.WriteLine("Kindergeld‐Berechnung"); Console.WriteLine("****************"); Console.WriteLine(); Console.Write("Anzahl Kinder : "); anzahlKinder = Convert.ToInt16(Console.ReadLine()); //Berechnungen switch (anzahlKinder) { case 0: kinderGeld = 0; break; case 1: kinderGeld = 154; break; case 2: kinderGeld = 308; break; case 3: kinderGeld = 462; break; default: kinderGeld = 3 * 154 + (anzahlKinder ‐ 3) * 179; break; } kinderGeldJahr = kinderGeld * 12; //Ausgabe Console.WriteLine(); Console.WriteLine("Kindergeld p.m. : {0,10:N}", kinderGeld); Console.WriteLine("Kindergeld p.a. : {0,10:N}", kinderGeldJahr); Console.ReadLine();
- Seite 100 -
.NET-Framework & C#.NET
6.2.1.4Mehrstufige Auswahl
Syntax
Beschreibung
Die mehrstufige Auswahl ist - wie die Bezeichnung bereits sagt – eine gestufte Fallunterscheidung, was auch das unten abgebildete Struktogramm
zeigt. Wenn folglich eine Bedingung mit true entschieden wird, werden die
nachfolgenden Bedingungen nicht mehr geprüft. Umgekehrt werden bei einer
mehrstufigen Auswahl ggf. alle Bedingungen durchgeprüft. Letzteres ist der
wesentliche Unterschied zur im folgenden Abschnitt dargestellten mehrseitigen Auswahl.
NSD
- Seite 101 -
.NET-Framework & C#.NET
Problemstellung
Zu erstellen ist ein C#-Programm, das anhand des Bruttoumsatzes den Rabatt
und den Nettoumsatz bestimmt. Dabei gelten folgende Bedingungen:
 bis 1.000,- € Umsatz wird 10% Rabatt gewährt
 ab 1.000,- € Umsatz wird 20% Rabatt gewährt
 ab 2.000,- € Umsatz wird 30% Rabatt gewährt
 ab 3.000,- € Umsatz wird 40% Rabatt gewährt
Screenshot
NSD
- Seite 102 -
.NET-Framework & C#.NET
Code
//Deklarationen double bruttoPreis, nettoPreis, rabatt; //Prozedur //Eingabe Console.WriteLine("Rabatt‐Berechnung"); Console.WriteLine("*****************"); Console.WriteLine(); Console.Write("Bruoot‐Preis: "); bruttoPreis = Convert.ToDouble(Console.ReadLine()); //Berechnung if (bruttoPreis < 1000) { rabatt = bruttoPreis * 0.1; } else { if (bruttoPreis < 2000) { rabatt = bruttoPreis * 0.2; } else { if (bruttoPreis < 3000) { rabatt = bruttoPreis * 0.3; } else { rabatt = bruttoPreis * 0.4; } } } nettoPreis = bruttoPreis ‐ rabatt; //Ausgabe Console.WriteLine(); Console.WriteLine("Brutto‐Preis : {0,12:N}", bruttoPreis); Console.WriteLine("Rabatt : {0,12:N}", rabatt); Console.WriteLine("Netto Preis : {0,12:N}", nettoPreis); Console.ReadLine();
- Seite 103 -
.NET-Framework & C#.NET
6.2.2 Iterationen
Die Iterations-Anweisungen oder Schleifen stellen einen weiteren wichtigen
Bereich der Kontrollstrukturen dar und werden im Folgenden erläutert. Grundsätzlich gibt es
 Schleifen, deren Anzahl an Schleifen-Durchläufen durch einen Zähler bestimmt werden und
 Schleifen, die durch eine logische Bedingung – z.B. solang der Restwert
> 0 ist – gesteuert werden.
Bei letzteren kann man wiederum, in Abhängig davon wo die Prüfung erfolgt zum Beginn oder zum Ende der Schleife – in
 kopf- oder
 fußgesteuerte
Schleifen differenzieren.
- Seite 104 -
.NET-Framework & C#.NET
6.2.2.1Zählergesteuerte Iteration
Syntax
Beschreibung
 Schleifenkopf
 counter = startwert
counter ist eine numerische Variable, der zu Beginn der Schleife ein startwert zugwiesen wird, bei der die Zählung beginnt.
 condition
condition ist eine Bedingung, die das Abbruchkriterium der Schleife formuliert. I.d.R. ist das eine < oder <= Abfrage auf den Endwert.
 nextStatement
ist eine Anweisung, die den Algorythmus zur Berechnung des nächsten
Zählerwertes festlegt.
 Schleifenkörper
 eine oder mehrere Anweisungen
NSD
- Seite 105 -
.NET-Framework & C#.NET
Problemstellung
Bei der vorliegenden Problemstellung, soll nach Eingabe des Anfangskapitals,
des Zinssatzes und der Laufzeit die Entwicklung des Kapitels dargestellt werden.
Screenshot
NSD
- Seite 106 -
.NET-Framework & C#.NET
Code
//Deklarationen double kapitalStart, kapitalEnde, zinsSatz; int laufzeit, zaehler; //Prozedur //Eingabe Console.WriteLine("Kapital‐Entwicklung"); Console.WriteLine("*******************"); Console.WriteLine(); Console.Write("Start‐Kapital : "); kapitalStart = Convert.ToDouble(Console.ReadLine()); Console.Write("Zinssatz : "); zinsSatz = Convert.ToDouble(Console.ReadLine()); Console.Write("Laufzeit : "); laufzeit = Convert.ToInt16(Console.ReadLine()); //Berechnung & Ausgabe Console.WriteLine(); Console.WriteLine("{0,4} {1,10}", "Jahr", "Kapital"); Console.WriteLine("****************"); kapitalEnde = kapitalStart; for (zaehler = 1; zaehler <= laufzeit; zaehler++) { kapitalEnde = kapitalEnde * (1 + zinsSatz / 100); Console.WriteLine("{0,4} {1,10:N}", zaehler, kapitalEnde); } Console.ReadLine();
- Seite 107 -
.NET-Framework & C#.NET
Problemstellung
Zu erstellen ist ein C#-Programm, das durch zwei zählergesteuerte Schleifen
eine 1 X 1 Tabelle erzeugt. Durch die Eingabe von Startwert, Endwert und
Schrittweite kann der Schleifendurchlauf bestimmt werden. Bei der ersten Version soll die Schleife aufsteigend durchlaufen werden, bei der zweiten Version
absteigend.
Screenshot
NSD
- Seite 108 -
.NET-Framework & C#.NET
Code 1
//Deklarationen double produkt; int start, ende, step, i, j; //Prozedur //Eingabe Console.Clear(); Console.WriteLine("1 * 1 ‐ Tabelle"); Console.WriteLine("***************"); Console.WriteLine(); Console.Write("Startwert : "); start = Convert.ToInt16(Console.ReadLine()); Console.Write("Endwert : "); ende = Convert.ToInt16(Console.ReadLine()); Console.Write("Schrtittweite : "); step = Convert.ToInt16(Console.ReadLine()); //Berechnungen und Ausgabe Console.WriteLine(); Console.WriteLine(); for (i = start; i <= ende; i = i + step) { for (j = 1; j <= 10; j++) { produkt = i * j; Console.Write("{0,4}", produkt); } Console.WriteLine(); } Console.ReadLine();
Code 2
for (i = ende; i > start; i = i ‐ step) { for (j = 1; j <= 10; j++) { produkt = i * j; Console.Write("{0,4}", produkt); } Console.WriteLine(); } - Seite 109 -
.NET-Framework & C#.NET
6.2.2.2 Bedingte Iteration - kopfgesteuert
Syntax
Beschreibung
 Schleifenkopf
 condition
condition ist eine logische Bedingung, die das Wiederholungskriterium
der Schleife formuliert.
 Schleifenkörper
 eine oder mehrere Anweisungen
 jeweils vor Durchführung der Anweisung wird eine Bedingung geprüft.
NSD
- Seite 110 -
.NET-Framework & C#.NET
Problemstellung
Zu erstellen ist ein C#-Programm, das nach Eingabe
 des Anschaffungswertes und
 des Abschreibungssatzes
den Restwertverlauf darstellt. Der Programmablauf soll über eine kopfgesteuerte Schleife realisiert werden. Bei der Formulierung des Abbruchkriteriums, ist
auf die Vermeidung von "Endlosschleifen" zu achten.
Screenshot
NSD
- Seite 111 -
.NET-Framework & C#.NET
Code
//Deklarationen double aw, rw, afaSatz, afaBetrag; int jahr; //Prozedur //Eingabe Console.WriteLine("Degressive Abschreibung"); Console.WriteLine("***********************"); Console.WriteLine(); Console.Write("Anschaffungswert : "); aw = Convert.ToDouble(Console.ReadLine()); Console.Write("AFA‐Satz : "); afaSatz = Convert.ToDouble(Console.ReadLine()); //Berechnung & Ausgabe Console.WriteLine(); Console.WriteLine("{0,4} {1,10}", "Jahr", "Restwert"); Console.WriteLine("****************"); rw = aw; jahr = 0; Console.WriteLine("{0,4} {1,10:N}", jahr, rw); while (rw > 100) { jahr++; afaBetrag = rw * afaSatz / 100; rw ‐= afaBetrag; onsole.WriteLine("{0,4} {1,10:N}", jahr, rw); } Console.ReadLine();
- Seite 112 -
.NET-Framework & C#.NET
6.2.2.3Bedingte Iteration - fußgesteuert
Syntax
Beschreibung
 Schleifenfuß
 condition
condition ist eine logische Bedingung, die das Wiederholungskriterium
der Schleife formuliert.
 Schleifenkörper
 eine oder mehrere Anweisungen
 Die Anweisung wird mind. 1x durchgeführt. Erst nach einer Durchführung
wird geprüft.
NSD
- Seite 113 -
.NET-Framework & C#.NET
Problemstellung
Das bereits bekannt Programm ist so zu programmieren, dass die Schleife
fußgesteuert wird.
NSD
- Seite 114 -
.NET-Framework & C#.NET
Code
//Deklarationen double aw, rw, afaSatz, afaBetrag; int jahr; //Prozedur //Eingabe Console.WriteLine("Degressive Abschreibung"); Console.WriteLine("***********************"); Console.WriteLine(); Console.Write("Anschaffungswert : "); aw = Convert.ToDouble(Console.ReadLine()); Console.Write("AFA‐Satz : "); afaSatz = Convert.ToDouble(Console.ReadLine()); //Berechnung & Ausgabe Console.WriteLine(); Console.WriteLine("{0,4} {1,10}", "Jahr", "Restwert"); Console.WriteLine("****************"); rw = aw; jahr = 0; Console.WriteLine("{0,4} {1,10:N}", jahr, rw); do { jahr++; afaBetrag = rw * afaSatz / 100; rw ‐= afaBetrag; Console.WriteLine("{0,4} {1,10:N}", jahr, rw); } while (rw > 100); Console.ReadLine();
- Seite 115 -
.NET-Framework & C#.NET
6.3 Übungen
6.3.1 Endwertmethode
Problemstellung
Zu erstellen ist ein Programm zur Darstellung der Endwert-Entwicklung einer
Investition bei den entsprechenden Eingaben.
Screenshot
NSD
- Seite 116 -
.NET-Framework & C#.NET
Code
//Deklarationen double investition, cashFlow, endWert, zinsSatz, zinsen; int laufzeit, jahr; //Prozedur //Eingabe Console.WriteLine("Endwert‐Methode"); Console.WriteLine("*******************"); Console.WriteLine(); Console.Write("Investition : "); investition = Convert.ToDouble(Console.ReadLine()); Console.Write("CashFlow : "); cashFlow = Convert.ToDouble(Console.ReadLine()); Console.Write("Zinssatz : "); zinsSatz = Convert.ToDouble(Console.ReadLine()); Console.Write("Laufzeit : "); laufzeit = Convert.ToInt16(Console.ReadLine()); //Berechnungen & Ausgabe Console.WriteLine(); endWert = investition * (‐1); for (jahr = 1; jahr <= laufzeit; jahr++) { zinsen = endWert * zinsSatz / 100; endWert = endWert + zinsen + cashFlow; Console.WriteLine("{0,4} {1,10:N} {2,10:N} {3,10:N}", jahr, cashFlow, zinsen, endWert); } Console.ReadLine();
- Seite 117 -
.NET-Framework & C#.NET
6.3.2 Degressive Abschreibung 1
Problemstellung
Zu erstellen ist ein Programm, das in etwas vereinfachter Form eine Tabelle
für eine degressive Abschreibung darstellt. Dabei existieren vorerst die folgenden Eingabegrößen:
 Anschaffungswert
 Degressiver Abschreibungssatz
 Abbruchkriterium
Eine Überprüfung des Abschreibungssatzes erfolgt vorerst nicht. Das Abbruchkriterium ist notwendig, um nicht bis zum Restwert = 0 abschreiben zu
müssen, was eine Endlosschleife mit Systemabbruch zur Folge hätte.
Screenshot
NSD
- Seite 118 -
.NET-Framework & C#.NET
Code
//Deklarationen double aw, anfangsWert, restWert, afaSatz, afaBetrag, abbruchKriterium; int jahr; //Prozedur //Eingabe Console.WriteLine("Degressive Abschreibung"); Console.WriteLine("***********************"); Console.WriteLine(); Console.Write("Anschaffungswert : "); aw = Convert.ToDouble(Console.ReadLine()); Console.Write("AfaSatz : "); afaSatz = Convert.ToDouble(Console.ReadLine()); Console.Write("AbbruchKriterium : "); abbruchKriterium = Convert.ToDouble(Console.ReadLine()); //Berechnungen & Ausgabe Console.WriteLine(); Console.WriteLine("{0,4} {1,10} {2,10} {3,10}", "Jahr", "Anfang", "AFA", "Restwert"); Console.WriteLine("*************************************"); Console.WriteLine("{0,4} {1,10:N} {2,10:N} {3,10:N}", 0, 0, 0, aw); jahr = 1; anfangsWert = aw; while (anfangsWert > abbruchKriterium) { afaBetrag = anfangsWert * afaSatz / 100; restWert = anfangsWert ‐ afaBetrag; Console.WriteLine("{0,4} {1,10:N} {2,10:N} {3,10:N}", jahr, anfangsWert, afaBetrag, restWert); anfangsWert = restWert; jahr++; } Console.ReadLine();
- Seite 119 -
.NET-Framework & C#.NET
6.3.3 Degressive Abschreibung 2
Problemstellung
Das bekannte Programm zur degressiven Abschreibung ist wie folgt zu modifizieren. Zu berücksichtigen sind die Eingabegrößen:
 Anschaffungswert, Nutzungsdauer und Abbruchkriterium
Anhand der Nutzungsdauer ist der AfA-Satz zu bestimmen. Dabei ist der degressive Afa-Satz das 2-fache linearen Afa-Satzes, maximal aber 20%. Der lineare AfA-Satz wird berechnet durch
Screenshot
NSD
- Seite 120 -
.NET-Framework & C#.NET
Code
//Deklarationen double aw, anfangsWert, restWert, afaSatzL, afaSatzD, afaBetrag, abbruchKriterium; int jahr, laufzeit; //Prozedur //Eingabe Console.WriteLine("Degressive Abschreibung"); Console.WriteLine("***********************"); Console.WriteLine(); Console.Write("Anschaffungswert : "); aw = Convert.ToDouble(Console.ReadLine()); Console.Write("Laufzeit : "); laufzeit = Convert.ToInt16(Console.ReadLine()); Console.Write("AbbruchKriterium : "); abbruchKriterium = Convert.ToDouble(Console.ReadLine()); //Berechnungen //Afa‐Satz afaSatzL = 100 / laufzeit; if (afaSatzL * 2 > 20) afaSatzD = 20; else afaSatzD = afaSatzL * 2; Console.WriteLine(); Console.WriteLine("AfaSatz degressiv : {0,4:N}%", afaSatzD); Console.WriteLine(); //Tabellenbeschrfitung Console.WriteLine(); Console.WriteLine("{0,4} {1,10} {2,10} {3,10}", "Jahr", "Anfang", "AFA", "Restwert"); Console.WriteLine("*************************************"); Console.WriteLine("{0,4} {1,10:N} {2,10:N} {3,10:N}", 0, 0, 0, aw); //Restwertberechung & Ausgabe jahr = 1; anfangsWert = aw; while (anfangsWert > abbruchKriterium) { afaBetrag = anfangsWert * afaSatzD / 100; restWert = anfangsWert ‐ afaBetrag; Console.WriteLine("{0,4} {1,10:N} {2,10:N} {3,10:N}", jahr, anfangsWert, afaBetrag, restWert); anfangsWert = restWert; jahr++; } - Seite 121 -
.NET-Framework & C#.NET
6.3.4 Prämienberechnung
Problemstellung
Zu erstellen ist ein Programm für die Berechnung von Prämien, die in Abhängigkeit vom Bruttogehalt und der Betriebszugehörigkeit berechnet werden. Es
gelten die folgenden Modalitäten:
Betriebszugehörigkeit
Prämie
0 bis < 1
1 bis < 3
3 bis < 10
sonst
10%
30%
50%
100%
Zusätzlich sind die folgenden Restriktionen zu beachten:
 minimale Prämie 100,- €
 maximale Prämie
2.000,- €
Ferner ist die Einagbe auf Plausibilität zu prüfen.
Screenshot
- Seite 122 -
.NET-Framework & C#.NET
NSD
- Seite 123 -
.NET-Framework & C#.NET
Code
//Deklarationen double gehalt, praemie, summe, jahre; //Prozedur //Eingabe Console.Clear(); Console.WriteLine("Prämien‐Berechnung"); Console.WriteLine("******************"); Console.WriteLine(); Console.Write("Gehalt : "); gehalt = Convert.ToDouble(Console.ReadLine()); Console.Write("Betriebszugehöirgkeit : "); jahre = Convert.ToDouble(Console.ReadLine()); //Eingabe‐Überprüfung if (gehalt <= 0 | jahre <= 0) { Console.WriteLine(); Console.WriteLine("falsche Eingabe ..."); Console.ReadLine(); return; } //Berechnung if (jahre < 1) praemie = gehalt * 0.1; else if (jahre < 3) praemie = gehalt * 0.3; else if (jahre < 10) praemie = gehalt * 0.5; else praemie = gehalt; if (praemie < 100) praemie = 100; if (praemie > 2000) praemie = 2000; summe = gehalt + praemie; //Ausgabe Console.WriteLine(); Console.WriteLine("Gehalt : {0,10:N}", gehalt); Console.WriteLine("Prämie : {0,10:N}", praemie); Console.WriteLine("Gesamtbetrag : {0,10:N}", summe); Console.ReadLine();
- Seite 124 -
.NET-Framework & C#.NET
6.3.5 Zinsrechnung
Problemstellung
Das nachstehende Programm stellt ein Menü für die Varianten der Zinsrechnung dar, da alle aus der Grundformel abgeleitet sind:
Screenshot
 Menü
 Fehlermeldung bei unzulässiger Eingabe
 Message beim Programmende
 Eingabe & Ausgabe bei „Berechnung der Zinsen“
- Seite 125 -
.NET-Framework & C#.NET
NSD
- Seite 126 -
.NET-Framework & C#.NET
Code
//Deklarationen double zinsen, kapital, zinsSatz; int tage, auswahl; //Prozedur do { //BildschirmAufbau Console.Clear(); Console.WriteLine("Menü für Zinsrechnung"); Console.WriteLine("*********************"); Console.WriteLine(); Console.WriteLine("Zinsen : 1"); Console.WriteLine("Kapital : 2"); Console.WriteLine("Prozentsatz : 3"); Console.WriteLine("Tage : 4"); Console.WriteLine(); Console.WriteLine("Abbruch : 0"); Console.WriteLine(); Console.Write("Eingabe : "); auswahl = Convert.ToInt16(Console.ReadLine()); //Berechnungen & Ausgabe switch (auswahl) { case 0: Console.Clear(); Console.WriteLine("Ende ‐ weiter mit Return"); Console.ReadLine(); break; case 1: //Bildschirmaufbau & Eingabe Console.Clear(); Console.WriteLine("Berechnung der Zinsen"); Console.WriteLine("*********************"); Console.WriteLine(); Console.Write("Kapital : "); kapital = Convert.ToDouble(Console.ReadLine()); Console.Write("Prozentsatz : "); zinsSatz = Convert.ToDouble(Console.ReadLine()); Console.Write("Tage : "); tage = Convert.ToInt16(Console.ReadLine()); //Berechnung zinsen = (kapital * zinsSatz * tage) / (100 * 360); - Seite 127 -
.NET-Framework & C#.NET
//Ausgabe Console.WriteLine(); Console.WriteLine("Zinsen {0,12:N}", zinsen); Console.WriteLine(); Console.WriteLine("weiter mit Return"); Console.ReadLine(); break; case 2: //Bildschirmaufbau & Eingabe Console.Clear(); Console.WriteLine("Berechnung des Kapitals"); Console.WriteLine("*********************"); Console.WriteLine(); Console.Write("Zinsen : "); zinsen = Convert.ToDouble(Console.ReadLine()); Console.Write("Prozentsatz : "); zinsSatz = Convert.ToDouble(Console.ReadLine()); Console.Write("Tage : "); tage = Convert.ToInt16(Console.ReadLine()); //Berechnung kapital = (zinsen * 100 * 360) / (zinsSatz * tage); //Ausgabe Console.WriteLine(); Console.WriteLine("Kapital {0,12:N}", kapital); Console.WriteLine(); Console.WriteLine("weiter mit Return"); Console.ReadLine(); break; case 3: //Bildschirmaufbau & Eingabe Console.Clear(); Console.WriteLine("Berechnung des Zinssatzes"); Console.WriteLine("*************************"); Console.WriteLine(); Console.Write("Zinsen : "); zinsen = Convert.ToDouble(Console.ReadLine()); Console.Write("Kapital : "); kapital = Convert.ToDouble(Console.ReadLine()); Console.Write("Tage : "); tage = Convert.ToInt16(Console.ReadLine()); - Seite 128 -
.NET-Framework & C#.NET
//Berechnung zinsSatz = (zinsen * 100 * 360) / (kapital * tage); //Ausgabe Console.WriteLine(); Console.WriteLine("Zinssatz {0,12:N}", zinsSatz); Console.WriteLine(); Console.WriteLine("weiter mit Return"); Console.ReadLine(); break; case 4: //Bildschirmaufbau & Eingabe Console.Clear(); Console.WriteLine("Berechnung der Laufzeit"); Console.WriteLine("***********************"); Console.WriteLine(); Console.Write("Zinsen : "); zinsen = Convert.ToDouble(Console.ReadLine()); Console.Write("Kapital : "); kapital = Convert.ToDouble(Console.ReadLine()); Console.Write("Zinssatz : "); zinsSatz = Convert.ToInt16(Console.ReadLine()); //Berechnung tage = Convert.ToInt16((zinsen * 100 * 360) / (kapital * zinsSatz)); //Ausgabe Console.WriteLine(); Console.WriteLine("Tage {0,12:N}", tage); Console.WriteLine(); Console.WriteLine("weiter mit Return"); Console.ReadLine(); break; default: Console.Clear(); Console.WriteLine("falsche Eingabe ‐ weiter mit Return"); Console.ReadLine(); break; } } while (auswahl != 0);
- Seite 129 -
.NET-Framework & C#.NET
7 Datentypen II - Array
Bei den bisherigen Variablen konnten in einer Variable immer nur ein Wert gespeichert werden. Hatte man beispielsweise eine Variable endWert vom Typ
double, so konnte dort eine relle Zahl abgelegt werden. Diese recht einfache
Struktur ist aber bei größeren Datenmengen sehr unflexibel.
Achtung: Wann immer Berechnungen durchgeführt werden sollen, ist ein Array
nötig. Es speichert Daten (z.B. aus einer Tabelle) eines Datentyps (z.B. double).
Bei der nachstehenden Anwendung werden bei drei Filialen die Umsätze für
das erste und zweite Halbjahr summiert. Hierfür müssten alleine für die Umsätze 6 Variablen und für die Summen weitere 6 Variabelen dekalriert werden.
Komplizierte wird es, wenn beispielsweise die Anzahl der Filialen flexibel sein
soll und diese erste nach dem Start des programms durch den Anwender angegeben werden. Damit ist während der Entwicklung die Anzahl der Variablen
nicht bekannt.
Alle diese Schwierigkeiten lassen sich mittels eines Arrays elegant lösen.
- Seite 130 -
.NET-Framework & C#.NET
7.1 Grundsätzliches zum Array
Struktur eines Arrays
Das Array basiert immer auf einem Basistyp, z.B. dem Typ double, string usw.
 Ein Mischen von Typen innerhalb eines Arrays ist daher nicht möglich.
Will man in einem Array alphanumerische Daten speichern, so geht das
nur mit dem Typ string; allerdings kann man dann auch nicht mit den Daten rechnen. Ist letzteres erforderlich, so benötigt man einen numerischen
Typ, beispielsweise den Typ double, kann dann aber keine alphabethischen Daten speichern.
 Ein Array kann man sich anschaulich als ein- oder zweidimensionale Matrix vorstellen. Das Array besitzt, wie alle Variabeln, einen Bezeichner. Für
den Bezeichner gelten die üblichen Konventionen.
 Eine einfache Variable wird direkt über den Bezeichner angesprochen.
Da dieser Bezeichner nur eine Speichermöglichkeit hat, sind keine weiteren Angaben notwendig. Im Falle eines Arrays ist das etwas anders, da
mehrere Speichermöglichkeiten unter dem Bezeichner existieren. Die
Speicherplätze eines Arrays werde systemseitig automatisch mit 0 beginnend durchnummeriert. Dieser Index wird dann in eckigen Klammner [ ]
nach dem Variablenbezeichner angegeben.
Eindimensionales Array
 Bezeichner des Arrays: namen
 Zuweisung: namen[0]="Meier";
 Lesen: Console.WriteLine(namen[0]);
- Seite 131 -
.NET-Framework & C#.NET
Zweidimensionales Array
 Bezeichner des Arrays: umsaetze
 Zuweisung: umsaetze[0,0]=10000;
 Lesen: Console.WriteLine(umsaetze[0;0]);
Array im Debugger
Mehrdimensionale Arrays
Grundsätzlich können auch Arrays mit mehr als zwei Dimensionen implementiert werden. Schwierigkeiten entstehen jedoch sehr häufig bei der Interpretation dieser Dimensionen. Von daher treten mehrdimensionale Arrays in der
Praxis sehr selten auf.
- Seite 132 -
.NET-Framework & C#.NET
7.2 Eindimensionales Array
Deklaration
Nachstehend die allgemeine Schreibweise für die Deklaration eines eindimensionalen Arrays
type[ ] identifier = new type[size]
sowie Beispiele für ein alphanumerisches ein numerisches Array
 string[ ] namen = new string[5]
 double[ ] zahlen = new double[11]
Merke:
 Im Gegensatz zur Deklaration einer einfachen Variablen folgen hier hinter
dem Typ die eckigen Klammern - z.B. double[ ].
 Danach folgt wie üblich der Bezeichner - in diesem Fall zahlen.
 Mittels des Schlüsselwortes new wird dann der Konstruktor aufgerufen
und ein Interger-Wert für die Anzahl der Speicherplätze übergeben - hier
new double[11]. Wichtig ist, dass dieser Wert die Anzahl der Speicherplätze darstellt. Er ist zu unterscheiden vom Index.
 Zu untercheiden sind: Index  Speicherplätze
Speichern von Werten
Das Speichern und Lesen von Variablen erfolgt im Grundsatz wie bisher. Allerdings muss im Zusammenhang mit dem Bezeichner immer der Index angegeben werden, da sonst nicht eindeutig geklärt ist, welche Speicherstelle angesprochen werden soll.
 namen[0] = Console.ReadLine();
 zahlen[0] = Convert.ToDouble(Console.ReadLine());
Lesen von Werten
 Console.WriteLine(namen[0]);
 Console.WriteLine(zahlen[0]);
Zugriff mittels Variablen
Der Index muss nicht in Form einer konkreten Zahl sondern kann auch als Variable angegeben werden. Dieses macht die Programmierung deutlich flexibler.
for(zeile = 1; zeile <= 5; zeile++)
Console.WriteLine(namen[zeile]);
- Seite 133 -
.NET-Framework & C#.NET
7.2.1 Eindimensionales alphanumerisches Array
Problemstellung
Bei dieser Anwendung sind nur fünf Namen einzugeben und diese danach
wieder auf den Bildschirm auszugeben. Beim Testen des Programmes setzen
Sie bitte einen Breakpoint bei der for-Schleife (Zeile 10) zum Einlesen der Daten. Durchlaufen Sie ab dort das Programm mittels der <F11>-Taste und verfolgen Sie die Zuweisung der eingegebenen Daten ins Array.
Screenshot
NSD (Nassi-Shneiderman-Diagramm/Struktogramm)
- Seite 134 -
.NET-Framework & C#.NET
Code
//Deklarationen int z; string[] namen = new string[5]; //Eingabe Console.WriteLine("NamensVerwaltung"); Console.WriteLine("****************"); Console.WriteLine(); for (z = 0; z <= 4; z++) { Console.Write("{0,2}. Name : ", z + 1); namen[z] = Console.ReadLine(); } //Ausgabe Console.WriteLine(); Console.WriteLine("NamensListe"); for (z = 0; z <= 4; z++) Console.WriteLine("{0,2}. Name : {1,10}", z+1, namen[z]); Console.ReadLine();
- Seite 135 -
.NET-Framework & C#.NET
7.2.2 Eindimensionales numerisches Array
Problemstellung
Dieses Beispiel unterscheidet sich von dem vorherigen nur dadurch dass das
Array nicht vom Typ string sondern vom Typ double ist. Dieses Beispiel wird in
dem etwas später folgenden Kapitel zum Rechnen im Array wieder aufgegriffen. Vorläufig sollen nur zehn Zahlen eingegeben werden. Verfolgen Sie mit
Hilfe des Debuggers die Zuweisung der Zahlen Zellen des Arrays.
Screenshot
NSD
- Seite 136 -
.NET-Framework & C#.NET
Code
//Deklarationen int z; double[] zahlen = new double[11]; //Prozedur //Eingabe Console.WriteLine("Eingabe von Zahlen"); Console.WriteLine("******************"); Console.WriteLine(); for (z = 0; z <= 9; z++) { Console.Write("{0,2} Zahl : ", z + 1); zahlen[z] = Convert.ToDouble(Console.ReadLine()); } Console.ReadLine();
- Seite 137 -
.NET-Framework & C#.NET
7.2.3 Eindimensionales, variables numerisches Array
Problemstellung
Die bereits bekannte Problemstellung wird in diesem Beispiel um einen weiteren Aspekt erweitert. Sehr häufig treten Problemstellungen auf, bei denen das
Array flexibel, z.B. in Abhängigkeit von User-Eingaben dimensioniert werden
muss.
Screenshot
NSD
Damit muss folglich die Grenze bei den Schleifen variabel gestaltet werden.
Betrachtet man hierzu einmal das Struktogramm des vorherigen Abschnittes,
so ergeben sich zwei Probleme:
 Die Instanziierung des Arrays kann nicht bei der Codierung mit festen
Werten erfolgen, da diese erst vom User eingegeben werden müssen.
 Das Abbruchkriterum mit "z <= 9" ist ebenfalls nur für eine Problemstellung mit 10 Zahlen geeignet und ist variabel zu gestalten.
Aufgrund dieser Anforderungen ergibt sich dann das nachstehende Struktogramm.
 Wichtig ist, dass das Abbruchkriterium der Schleife "anzahl - 1" ist. Dieses ergibt sich aus dem 0-basierten Index des Arrays. Will man bspw.
fünf Datensätze eingeben, so ist die Anzahl der Felder im Array 5, der Index läuft aber von 0 bis 4. D.h. der Index des letzten Feldes ist immer um
1 geringer als die absoulte Anzahl.
 Die Instanziierung des Arrays muss jetzt in zwei Schritten erfolgen. Im unterstehenden Code wird erst nur die Variable deklariert:
double[ ] zahlen
Nach der Eingabe der Anzahl erfolgt dann die Instanziierung durch
zahlen = new double[anzahl]
- Seite 138 -
.NET-Framework & C#.NET
Code
//Deklarationen int zeile, anzahl; double[] zahlen; //Prozedur Console.WriteLine("Eingabe von Zahlen"); Console.WriteLine("******************"); Console.WriteLine(); //Anzahl der Werte Console.Write("Anzahl der Zahlen : "); anzahl=Convert.ToInt32(Console.ReadLine()); Console.WriteLine(); //Dimensionierung des Arrays zahlen = new double[anzahl]; //Eingabe for (zeile = 0; zeile <= anzahl‐1; zeile++) { Console.Write("{0,2} Zahl : ", zeile + 1); zahlen[zeile] = Convert.ToDouble(Console.ReadLine()); } - Seite 139 -
.NET-Framework & C#.NET
7.3 Zweidimensionales Array
Deklaration
Nachstehend die allgemeine Schreibweise für die Deklaration eines zweidimensionalen Arrays
 type[,] identifier = new type[size, size]
sowie Beispiele für ein alphanumerisches ein numerisches Array
 string[,] namen = new string[5, 4]
 double[,] zahlen = new double[10, 3]
Bei der Deklaration ist wichtig, dass bei einem zweidimensionalen Array in den
eckigen Klammern des Typs bereits ein Komma steht. Hierdurch wird festgelegt, dass das Array zwei Dimensionen besetzt. Beim Aufruf des Konstrukteurs
müssen dann auch in eckigen Klammern zwei Integer-Werte übergeben werden.
Speichern von Werten
Beim Zugriff auf die Speicherplätze eines zweidimensionalen Arrays ist nur zu
beachten, dass auch zwei Indices angegeben werden.
 namen[0, 0] = Console.ReadLine();
 zahlen[0, 0] = Convert.ToDouble(Console.ReadLine());
Lesen von Werten


Console.WriteLine(namen[0, 0]);
Console.WriteLine(zahlen[0, 0]);
Zugriff mittels Variablen
Wie bereits bekannt, können auch beim zweidimensionalen Array Integer-Variablen als Indizien verwendet werden.
for(zeile = 1; zeile <= 5; zeile++)
for (spalte = ; spalte <= 4; spalte++)
Console.WriteLine(namen[zeile, spalte]);
- Seite 140 -
.NET-Framework & C#.NET
7.3.1 Zweidimensionales numerisches Array
Problemstellung
Bei dieser Anwendung zum numerischen, zweidimensionalen Array sollen von
drei Filialen die Umsatzzahlen eines ersten und eines zweiten Halbjahres einund dann in Tabellenform ausgegeben werden. Berechnungen sind hier noch
nicht vorgesehen.
Screenshot
NSD
- Seite 141 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] umsaetze = new double[3, 2]; int z, s; //Prozedur //Eingabe Console.WriteLine("Filial‐Umsätze"); Console.WriteLine("**************"); Console.WriteLine(); for (z = 0; z <= 2; z++) for (s = 0; s <= 1; s++) { Console.Write("Filiale {0,2}, Halbjahr {1,2} : ", z + 1, s + 1); umsaetze[z, s] = Convert.ToDouble(Console.ReadLine()); } //Ausgabe Console.WriteLine(); Console.WriteLine("Umsatz‐Tabelle"); Console.WriteLine("**************"); Console.WriteLine(); Console.WriteLine("{0,10} {1,15} {2,15}", "Filiale", "1. Halbjahr", "2. Halbjahr"); Console.Write‐
Line("******************************************"); for (z = 0; z <= 2; z++) Console.WriteLine("Filiale {0,2} {1,15:N} {2,15:N}", z + 1, umsaetze[z, 0], umsaetze[z, 1]); Console.ReadLine();
- Seite 142 -
.NET-Framework & C#.NET
7.3.2 Zweidimensionales, variables numerisches Array
Problemstellung
Bei dieser Anwendung zum numerischen, zweidimensionalen Array geht es
erneut um eine variable Dimensionierung des Arrays. Der Anwender kann
auch die Anzahl der gewünschten Filialen eingeben.
 Instanziierung des Array auf Basis der Benutzereingaben
 variable Steuerung der Eingabe
 variable Steuerung der Ausgabe
Screenshot
NSD
- Seite 143 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] umsaetze; int anzahl, z, s; //Prozedur //Eingabe Console.WriteLine("Filial‐Umsätze"); Console.WriteLine("**************"); Console.WriteLine(); //Aufbau Array Console.Write("Anzahl der Filialen : "); anzahl = Convert.ToInt16(Console.ReadLine()); umsaetze = new double[anzahl+1, 3]; //Eingabe for (z = 0; z <= anzahl‐1; z++) for (s = 0; s <= 1; s++) { Console.Write("Filiale {0,2}, Halbjahr {1,2} : ", z + 1, s + 1); umsaetze[z, s] = Convert.ToDouble(Console.ReadLine()); } //Ausgabe Console.WriteLine(); Console.WriteLine("Umsatz‐Tabelle"); Console.WriteLine("**************"); Console.WriteLine(); Console.WriteLine("{0,10} {1,15} {2,15}", "Filiale", "1. Halbjahr", "2. Halbjahr"); Console.WriteLine("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
‐‐‐‐‐‐‐‐‐"); for (z = 0; z <= anzahl‐1; z++) Console.WriteLine("Filiale {0,2} {1,15:N} {2,15:N}", z + 1, umsaetze[z, 0], umsaetze[z, 1]); Console.ReadLine();
- Seite 144 -
.NET-Framework & C#.NET
7.4 Rechnen im Array
7.4.1 Rechnen im eindimensionalen Array
Aufbau des Arrays
 Anzahl der Speicherstellen: 11
 Index: 0 bis 10
 Summe in Speicherzelle 10
Prinzip der Addition
1. Schritt
zahlen[10] = zahlen[10] + zahlen[0];
zahlen[10] = zahlen[10] + zahlen[1];
zahlen[10] = zahlen[10] + zahlen[2];
...
zahlen[10] = zahlen[10] + zahlen[9];
2. Schritt
for (zeile = 0; zeile <= 9; zeile++)
zahlen[10] = zahlen[10] + zahlen[zeile]
Dieser Algorithmus umfasst nur noch zwei Zeilen und ist unabhängig von der
Anzahl der zu addierenden Werte. Es ist ausschließlich im Schleifenkopf das
Abbruchkriterium auf einen beliebigen anderen Wert zu setzen.
- Seite 145 -
.NET-Framework & C#.NET
NSD
Code
//Deklarationen int z; double[] zahlen = new double[11]; //Prozedur //Eingabe Console.WriteLine("Eingabe von Zahlen"); Console.WriteLine("******************"); Console.WriteLine(); for (z = 0; z <= 9; z++) { Console.Write("{0,2} Zahl : ", z + 1); zahlen[z] = Convert.ToDouble(Console.ReadLine()); } //Berechnung for (z = 0; z <= 9; z++) zahlen[10] = zahlen[10] + zahlen[z]; //Ausgabe Console.WriteLine(); Console.WriteLine("Summe : {0,5:N}", zahlen[10]); - Seite 146 -
.NET-Framework & C#.NET
7.4.2 Rechnen im eindimensionalen, variablen Array
Anzahl versus Index
Bei den nachstehenden Erläuterungen gehen wir davon aus, dass die Anzahl
der zu erfassenden Daten in der Variabel anzahl gespeichert wird.
 Der Inhalt der Variablen anzahl wird zum einen bei der Deklaration für die
Anzahl der Speicherplätze benötigt. Hier wird der Inhalt dieser Variable
als die physische Anzahl angesehen.
 Des Weiteren wird der Inhalt dieser Variablen häufig in Schleifen beim
Zugriff auf die Speicherplätze verwendet. Hierbei wird sie jedoch als Index interpretiert, der immer null-basiert ist.
Summation bei flexibler Anzahl
 Speichern der Summe im Array => Anzahl der Speicherplätze "anzahl+1".
 Index für die Werte: 0 bis "anzahl-1".
 Index für die Summe: "anzahl".
- Seite 147 -
.NET-Framework & C#.NET
Deklaration im Code
double[] zahlen;
zahlen = new double[anzahl+1];
Screenshot
NSD
- Seite 148 -
.NET-Framework & C#.NET
Code
//Deklarationen int zeile, anzahl; double[] zahlen; //Prozedur //Eingabe Console.WriteLine("Eingabe von Zahlen"); Console.WriteLine("******************"); Console.WriteLine(); //Anzahl der Werte Console.Write("Anzahl der Zahlen : "); anzahl=Convert.ToInt32(Console.ReadLine()); Console.WriteLine(); //Dimensionierung des Arrays zahlen = new double[anzahl+1]; //Eingabe for (zeile = 0; zeile <= anzahl‐1; zeile++) { Console.Write("{0,2} Zahl : ", zeile + 1); zahlen[zeile] = Convert.ToDouble(Console.ReadLine()); } //Berechnung for (zeile = 0; zeile <= anzahl‐1; zeile++) zahlen[anzahl] = zahlen[anzahl] + zahlen[zeile]; //Ausgabe Console.WriteLine(); Console.WriteLine("Summe : {0,5:N}", zahlen[anzahl]); Console.ReadLine();
- Seite 149 -
.NET-Framework & C#.NET
7.4.3 Rechnen im zweidimensionalen Array
Struktur des Arrays
 Berechnung des Jahresumsatzes die Filiale.
 Berechnung des gesamten Umsatzes über alle Filialen je Halbjahr.
 Berechnung des Gesamtumsatzes im Jahr.
Berechnung der Spaltensummen
 Summation der 1. Spalte
for (zeile = 0; zeile <= 2; zeile++)
umsaetze[3] = umsaetze[3] + umsaetze[zeile]
for (zeile = 0; zeile <= 2; zeile++)
umsaetze[3,0] = umsaetze[3,0] + umsaetze[zeile,0]
 Summation der 2. Spalte
for (zeile = 0; zeile <= 2; zeile++)
umsaetze[3,1] = umsaetze[3,1] + umsaetze[zeile,1]
 Verallgemeinerung für beliebig viele Spalte
for(spalte = 0; spalte <=1; spalte++)
for (zeile = 0; zeile <= 2; zeile++)
umsaetze[3,1] = umsaetze[3,1] + umsaetze[zeile,1]
Berechnung der Zeilensummen
 Summation der 1. Zeile
for(spalte = 0; spalte <= 1; spalte++)
umsaetze[0,2]=umsaetze[0,2]+umsaetze[0,spalte];
 Summation der 2. Zeile
for(spalte = 0; spalte <= 1; spalte++)
umsaetze[1,2]=umsaetze[1,2]+umsaetze[1,spalte];
 Verallgemeinerung für beliebig viele Zeilen
for(zeile = 0; zeile <= 3; zeile++)
for(spalte = 0; spalte <= 1; spalte++)
umsaetze[zeile,2]=umsaetze[zeile,2]+umsaetze[1,spalte];
- Seite 150 -
.NET-Framework & C#.NET
Screenshot
NSD
- Seite 151 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] umsaetze = new double[4, 3]; int z, s; //Prozedur //Eingabe Console.WriteLine("Filial‐Umsätze"); Console.WriteLine("**************"); Console.WriteLine(); for (z = 0; z <= 2; z++) for (s = 0; s <= 1; s++) { Console.Write("Filiale {0,2}, Halbjahr {1,2} : ", z + 1, s + 1); umsaetze[z, s] = Convert.ToDouble(Console.ReadLine()); } //Zeilensummen for (z = 0; z <= 2; z++) for (s = 0; s <= 1; s++) umsaetze[z, 2] = umsaetze[z, 2] + umsaetze[z, s]; //Spaltensummen for (s = 0; s <= 2; s++) for (z = 0; z <= 2; z++) umsaetze[3, s] = umsaetze[3, s] + umsaetze[z, s]; - Seite 152 -
.NET-Framework & C#.NET
//Ausgabe Console.WriteLine(); Console.WriteLine("Umsatz‐Tabelle"); Console.WriteLine("**************"); Console.WriteLine(); Console.WriteLine("{0,10} {1,15} {2,15} {3,15}", "Filiale", "1. Halbjahr", "2. Halbjahr", "Summe"); Console.WriteLine("‐…"); for (z = 0; z <= 2; z++) Console.WriteLine("Filiale {0,2} {1,15:N} {2,15:N} {3,15:N}", z + 1, umsaetze[z, 0], umsaetze[z, 1], umsaetze[z, 2]); Console.WriteLine("‐…"); Console.WriteLine("Summe {0,15:N} {1,15:N} {2,15:N}", umsaetze[3, 0], umsaetze[3, 1], umsaetze[3, 2]); Console.WriteLine("=…"); Console.ReadLine();
- Seite 153 -
.NET-Framework & C#.NET
7.4.4 Rechnen im zweidimensionalen, variablen Array
Struktur des Arrays
Schleifensteuerung am Beispiel der Eingabe-Schleife
Screenshot
- Seite 154 -
.NET-Framework & C#.NET
NSD
- Seite 155 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] umsaetze; int anzahl, z, s; //Prozedur //Eingabe Console.WriteLine("Filial‐Umsätze"); Console.WriteLine("**************"); Console.WriteLine(); //Aufbau Array Console.Write("Anzahl der Filialen : "); anzahl = Convert.ToInt16(Console.ReadLine()); umsaetze = new double[anzahl+1, 3]; //Eingabe for (z = 0; z <= anzahl‐1; z++) for (s = 0; s <= 1; s++) { Console.Write("Filiale {0,2}, Halbjahr {1,2} : ", z + 1, s + 1); umsaetze[z, s] = Convert.ToDouble(Console.ReadLine()); } //Zeilensummen for (z = 0; z <= anzahl‐1; z++) for (s = 0; s <= 1; s++) umsaetze[z, 2] = umsaetze[z, 2] + umsaetze[z, s]; - Seite 156 -
.NET-Framework & C#.NET
//Spaltensummen for (s = 0; s <= 2; s++) for (z = 0; z <= anzahl‐1; z++) umsaetze[anzahl, s] = umsaetze[anzahl, s] + umsaetze[z, s]; //Ausgabe Console.WriteLine(); Console.WriteLine("Umsatz‐Tabelle"); Console.WriteLine("**************"); Console.WriteLine(); Console.WriteLine("{0,10} {1,15} {2,15} {3,15}", "Filiale", "1. Halbjahr", "2. Halbjahr", "Summe"); Console.WriteLine("‐…"); for (z = 0; z <= anzahl‐1; z++) Console.WriteLine("Filiale {0,2} {1,15:N} {2,15:N} {3,15:N}", z + 1, umsaetze[z, 0], umsaetze[z, 1], umsaetze[z, 2]); Console.WriteLine("‐…"); Console.WriteLine("Summe {0,15:N} {1,15:N} {2,15:N}", umsaetze[anzahl, 0], umsaetze[anzahl, 1], umsaetze[anzahl, 2]); Console.WriteLine("=…"); Console.ReadLine();
- Seite 157 -
.NET-Framework & C#.NET
7.5 Übungen
7.5.1 Gewinn-Ermittlung (Array fix)
Bei dem folgenden Programm soll für vier Produkte der Einkaufs- und der Verkaufspreis eingegeben werden. Die Eingaben werden in einem Array erfasst.
Bei den Berechnungen wird der Gewinn absolut als Differenz zwischen EK
und VK und prozentual zum EK innerhalb des Array ermittelt und gespeichert.
Des Weiteren soll von den ersten drei Spalten die Summe berechnet werden.
Der nachstehende ScreenShot veranschaulicht die Berechnungen.
Screenshot
- Seite 158 -
.NET-Framework & C#.NET
NSD
- Seite 159 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] gewinn = new double[5, 4]; int z, s; //Prozedur //Eingabe Console.WriteLine("Eingabe von Einkaufspreis und Verkaufspreis"); Console.WriteLine("*…"); Console.WriteLine(); for (z = 0; z <= 3; z++) { Console.Write("EK Produkt {0,2}: ", z + 1); gewinn[z, 0] = Convert.ToDouble(Console.ReadLine()); Console.Write("VK Produkt {0,2}: ", z + 1); gewinn[z, 1] = Convert.ToDouble(Console.ReadLine()); } //Berechnungen Gewinn (absolut & prozentual) for (z = 0; z <= 3; z++) { gewinn[z, 2] = gewinn[z, 1] ‐ gewinn[z, 0]; gewinn[z, 3] = gewinn[z, 2] / gewinn[z, 0] * 100; } - Seite 160 -
.NET-Framework & C#.NET
//Berechnung Spaltensummen for (s = 0; s <= 2; s++) { for (z = 0; z <= 3; z++) { gewinn[4, s] = gewinn[4, s] + gewinn[z, s]; } } //Ausgabe Console.WriteLine(); Console.WriteLine("Liste überr alle Produkte"); Console.WriteLine("*************************"); Console.WriteLine(); Console.WriteLine("Produkt EK VK Gewinn(abs) Gewinn(%) "); Console.WriteLine("*…"); for (z = 0; z <= 3; z++) { Console.WriteLine("Produkt {0,2} {1,10:N} {2,10:N} {3,10:N} {4,10:N}", z + 1, gewinn[z, 0], gewinn[z, 1], gewinn[z, 2], gewinn[z, 3]); } Console.WriteLine("‐…"); Console.WriteLine("Summe {0,10:N} {1,10:N} {2,10:N} {3,10:N}", gewinn[4, 0], gewinn[4, 1], gewinn[4, 2], gewinn[4, 3]); Console.WriteLine("=…"); - Seite 161 -
.NET-Framework & C#.NET
7.5.2 Gewinn-Ermittlung (Array variabel)
Bei dem nachstehenden Beispiel wurde die Problemstellung insofern geändert, dass die Anzahl der Produkte flexibel ist. Diese wird als erstes erfasst.
Danach wird das Array dimensioniert. Die Schleifen bei der Eingabe, den Berechnungen und der Ausgabe sind entsprechend variabel zu programmieren.
Im Wesentlich handelt es sich dabei um eine variable Obergrenze bei den
Schleifen.
Screenshot
- Seite 162 -
.NET-Framework & C#.NET
NSD
- Seite 163 -
.NET-Framework & C#.NET
Code
//Deklarationen double[,] gewinn; int z, s, anzahl; //Prozedur //Eingabe Console.WriteLine("Eingabe von Einkaufspreis und Verkaufspreis"); Console.WriteLine("*******************************************"); Console.WriteLine(); //Bestimmung des Arrays Console.Write("Anzahl der Produkte : "); anzahl = Convert.ToInt16(Console.ReadLine()); gewinn = new Double[anzahl + 1, 4]; for (z = 0; z <= anzahl ‐ 1; z++) { Console.Write("EK Produkt {0,2}: ", z + 1); gewinn[z, 0] = Convert.ToDouble(Console.ReadLine()); Console.Write("VK Produkt {0,2}: ", z + 1); gewinn[z, 1] = Convert.ToDouble(Console.ReadLine()); } //Berechnungen Gewinn (absolut & prozentual for (z = 0; z <= anzahl ‐ 1; z++) { gewinn[z, 2] = gewinn[z, 1] ‐ gewinn[z, 0]; gewinn[z, 3] = gewinn[z, 2] / gewinn[z, 0] * 100; - Seite 164 -
.NET-Framework & C#.NET
} //Berechnung Spaltensummen for (s = 0; s <= 2; s++) { for (z = 0; z <= anzahl ‐ 1; z++) { gewinn[anzahl, s] = gewinn[anzahl, s] + gewinn[z, s]; } } //Ausgabe Console.WriteLine(); Console.WriteLine("Liste überr alle Produkte"); Console.WriteLine("*************************"); Console.WriteLine(); Console.WriteLine("Produkt EK VK Gewinn(abs) Gewinn(%) "); Console.WriteLine("**************************************************************"); for (z = 0; z <= anzahl ‐ 1; z++) { Console.WriteLine("Produkt {0,2} {1,10:N} {2,10:N} {3,10:N} {4,10:N}", z + 1, gewinn[z, 0], gewinn[z, 1], gewinn[z, 2], gewinn[z, 3]); } Console.WriteLine("‐…"); Console.WriteLine("Summe {0,10:N} {1,10:N} {2,10:N} {3,10:N}", gewinn[anzahl, 0], gewinn[anzahl, 1], gewinn[anzahl, 2], gewinn[anzahl, 3]); Console.WriteLine("=…"); - Seite 165 -
.NET-Framework & C#.NET
C. Klassen der FCL & Windowsanwendungen
Wie bereits mehrfach angesprochen, behandeln wir in diesem Modul zwei
grundlegende Bereiche:
 zum einen die Programmiersprache C# und
 zum anderen die Klassen der FCL.
Im dritten Teil des Skripts befassen wir uns nun mit Teilen der FCL. Die FCL
selbst beinhaltet eine Vielzahl von Klassen.Diese beinhalten dann wiederum
Methoden(), Ereignisse und Eigenschaften. So kennt beispielsweise die
Klasse Convert die Methode ToDouble(), mit deren Hilfe z.B. ein String in eine
Zahl vom Type double konvertiert werden kann.
8 .NET-Entwicklungsumgebung - Teil 2
In diesem Kapitel wird die .NET-Entwicklungsumgebung noch einmal im Gesamtzusammenhang erläutert.
Bereits in Kapitel 3 (Teil A des Skripts) wurde auf die .NET-Entwicklung eingegangen. Führen Sie sich bitte die wichtigsten Inhalte hieraus nochmal zu Gemüte. In diesem Kapitel wird das Wissen über die .NET IDE vertieft. Hier noch
einmal ein Reminder auf Kapitel 3:
Die .NET-Welt besteht - wie bereits mehrfach erläutert - aus den beiden Komponenten:
 .NET-Framework (Rahmenstruktur, welche Klassen usw. bereitstellt)
 Entwicklungsumgebung Visual Studio (hier programmieren wir)
Mit der FCL (Klassenbibliothek) als dem wesentlichen Bestandteil des .NETFrameworks haben wir uns in den vorherigen Kapiteln schon ausführlich beschäftigt. Jetzt steht die IDE - die Entwicklungsumgebung in Visual Studio - im
Fokus.
Im Gegensatz zur Umgebung Visual Studio .NET ist C# unsere Programmiersprache! Sie funktioniert auch unabhängig von Viusal Studio in alternativen
Entwicklungsumgebungen. Ggf. kann das auch ein vollkommen unkomfortabler Editor sein. Der Quellcode muss nur mittels des .NET-Compilers übersetzt
werden.
- Seite 166 -
.NET-Framework & C#.NET
8.1 Ansicht der IDE
Designer-Ansicht
Code-Ansicht
- Seite 167 -
.NET-Framework & C#.NET
Umschalten zwischen den Ansichten
 Tastenkombinationen
 Code-Ansicht: F7
 Designer-Ansicht: Umschalt + F7
 Umschalten über das Menü
Bestandteile und Fenster einer Windows-Anwendung
Diese Datei enthält den C#-Code, den der Entwickler für
die Form programmiert.
Unter diesem Register wird der Designer zum Entwurf der
Form1.cs Form aktiviert. Da diese graphischen Elemente in Code
[Entwurf] umgesetzt werden, gibt es keine entsprechende Datei im
Explorer.
Hier wird der auf Basis des Design-Entwurfs der von der
Form1.Desig- IDE generierte Code abgelegt. D.h. alle Aktionen die beim
ner.cs
Entwurf per Drag & Drop durchgeführt werden, werden
vom Generator in entsprechenden Code umgesetzt.
Dieser Programmteil enthält mit der Main-Methode den
Program.cs
Start des C#-Programms.
Form1.cs
- Seite 168 -
.NET-Framework & C#.NET
8.2 Rückblick: Beispiel für Windows-Anwendung
Was ist eine Windows-Anwendung?
Aufbau einer Form in der Designer-Ansicht
Eigenschaften
- Seite 169 -
.NET-Framework & C#.NET
Ereignisbasierte Methoden in der Code-Ansicht
 Methodenrumpf für ereignisbasierte Methode erzeugen
 Code für Ereignis-Methode
- Seite 170 -
.NET-Framework & C#.NET
8.3 Rückblick: Anatomie von Windows-Anwendungen
Ablauflogik beim Aufruf
- Seite 171 -
.NET-Framework & C#.NET
Form1.Designer.cs
- Seite 172 -
.NET-Framework & C#.NET
Form1.cs
Program.cs
- Seite 173 -
.NET-Framework & C#.NET
9 Objektorientierte Programmierung - Theorie Teil 2
- Seite 174 -
.NET-Framework & C#.NET
9.1 Klassen & Klassenmember
Struktur
Namespace
 eigenen Anwendungen
 FCL
Mitglieder eines Namespace (Namespace-Member)
 Klassen
 Zugriffsmodifizierer
 Mitglieder von Klassen (Class-Member)
 Konstruktor
 Methoden
 Ereignisse (Events)
 Felder
 Eigenschaften (Properties)
 Abgrenzung Eigenschaften & Felder
Differenzierung von Methoden
 Überladene Methoden
 Statische Methoden
- Seite 175 -
.NET-Framework & C#.NET
9.2 Vererbung & Instanziierung
Vererbung
Übertragung der Struktur (Eigneschaften, Methoden, Ereignisse …) einer
Klasse auf eine neue Klasse
Klassenhierarchie
Instanziierung
Klasse => Objekt
Wirkungsweise von Vererbung & Instanziierung
- Seite 176 -
.NET-Framework & C#.NET
9.3 Vererbung bei Windows-Anwendungen
Grundidee
Zentrale Frage: Wie und wo wird das im Code realisiert?
 Die Form-Klasse der FCL bildet die Basis-Klasse für die neue Klasse; sie
enthält somit die Grundinformationen/Eigenschaften (Member)
 Die abgeleitete Klasse ist die neu zu erstellende Form, die einige weitere Elemente wie den Button und das Label enthält.
Entscheidend ist die folgende Anweisung:
public partial class Form1 : Form
Vernachlässigt man vorerst die Modifizierer public partialso bleibt als
Kern die folgende Anweisung übrig, durch die die Vererbung realisiert wird:
class Form1 : Form
Beispiel Button-Klasse
class myButton : Button
- Seite 177 -
.NET-Framework & C#.NET
9.4 Instanziierung bei Windows-Anwendungen
Instanziierung im Designer
Instanziierung im Code
Der generierte Code in der Designer.cs
this.btnStart.Location = new System.Drawing.Point(187, 12); this.btnStart.Name = "btnStart"; this.btnStart.Size = new System.Drawing.Size(75, 23); this.btnStart.TabIndex = 0; this.btnStart.Text = "Start"; this.btnStart.UseVisualStyleBackColor = true; this.btnStart.Click += new System.EventHandler(this.btnStart_Click);  Instanziierung
this.button1 = new System.Windows.Forms.Button();
 Festlegung der Eigenschaften
(im Eigenschaftenfenster oder im Designer geändert)
this.button1.Name = "button1";
this.button1.Text = "Ausgabe";
- Seite 178 -
.NET-Framework & C#.NET
9.5 Klassen der FCL & Klassenmember
Aktivierung des Objekts
Eigenschaften
 Änderung von Eigenschaften in der IDE
 Änderung von Eigenschaften durch Code
label1.Text = "Hello World";
Methoden
Console.WriteLine();
Console.ReadLine();
lblAusgabe.Hide();
- Seite 179 -
.NET-Framework & C#.NET
Ereignisse
Aktivieren der Ereignisansicht:
Konstruktor
this.btnStart = new System.Windows.Forms.Button();
- Seite 180 -
.NET-Framework & C#.NET
9.6 Eigenen Klassen & Klassenmember
Idee
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnStart_Click (object sender, EventArgs e) { lblAusgabe.Text = "Hello World !"; } private void btnEnde_Click (object sender, EventArgs e) { this.Close(); } Ereignisse & Methoden
Unterscheidung der beiden Begriffe „Ereignis“ und „Methode“.
Struktur einer ereignisorientierten Methode
 Diese Methode wird beim Auftreten des Click-Ereignis bei dem Objekt
Button btnStart ausgeführt.
 Der Bezeichner der Methode btnStart_Click
Bezeichner des Ereignisses & Bezeichner des Objekts
 Zugriffsmodifizierer private
Im Moment soll hierzu nur erläutert werden, dass diese Methode damit
nur innerhalb eines bestimmten Bereiches verwendet werden kann.
 Parameter der Methode:
Input-Parameter: object sender und System.EventArgs e
Output-Parameter: kein Parameter daher void
- Seite 181 -
.NET-Framework & C#.NET
Einbindung einer ereignisorientierten Methode
Desinger.cs
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
Merke
 Es darf daher auf keinen Fall der obige Methoden-Kopf manuell aufgebaut werden. Es würde damit die Anbindung an das entsprechende Event
fehlen.
 Man darf daher auch nicht einen versehentlich erzeugten Methoden-Kopf
einfach löschen. Damit würde das Event-Handling auf eine nicht existierende Methode verweisen und einen Fehler erzeugen.
 Hat man versehentlich einen Methoden-Kopf erzeugt, so muss man nicht
nur diesen sondern auch das entsprechende Eventhandling in der Designer.cs löschen.
Standard-Event
 Doppleklicken auf Objekt in der IDE erzeugt einen Methodenkopf für das
Standard-Event
 Bei anderen Event sist der Weg über die Ereignis-Ansicht des Eigenschaften-Fensters notwendig.
C#-Anweisungen einer ereignisorientierten Methode
 Objekteigenschaften dynamisch ändern
lblAusgabe.Text = "Hello World !"; 
Objektmethoden im Code verwenden
private void btnEin_Click(object Sender, EventArgs e)
{
lblAusgabe.Show();
}
- Seite 182 -
.NET-Framework & C#.NET
10 Namespace System.Windows.Forms
In diesem Kapitel werden die zentralen Klassen des Namespace System.Windows.Forms dargestellt. In diesem Namespace sind alle für die Entwicklung von Windows-Oberflächen notwendigen Klassen - wie z.B. der LabelKlasse, der Button-Klasse usw. - zusammengefasst.
10.1 Strukturen des Namespace System.Windows.Forms
Einordnung des Namespac Windows.System.Forms
 Die Klassen, die direkt auf einer Form instanziiert werden, werden als
Steuerelemente – auch Controls – bezeichnet.
 Die am häufigsten verwendeten Klassen dieses Namespace befinden
sich auch in der Toolbar.
Toolbar - Steuerelemente in der VS-Entwicklungsumgebung
- Seite 183 -
.NET-Framework & C#.NET
Erweiterung der Toolbar
Die Toolbar kann jeder Entwickler den eigenen Bedürfnissen anpassen. Durch
Klicken der rechten Maustaste auf der Toolbar gelangt man in das nachstehende Kontextmenü.
- Seite 184 -
.NET-Framework & C#.NET
Struktur der Dokumentation
- Seite 185 -
.NET-Framework & C#.NET
10.2 Überblick
Grundsätzlich ist es schwierig alle Klassen dieses Namespaces systematisch
zu differenzieren. Wenn dieses komplett gelänge, könnte man anhand dieser
Liste ausgehend von einer Problemstellung die möglichen Gestaltungsoptionen ablesen. Die bei den nachstehenden Listen stellen in Ansätzen eine solche Hilfe dar.
 Die erste Liste, die Kategorien, ist der Online-Dokumentation entnommen. Diese Liste beschreibt die Kategorien der Klassen.
 Die zweite Liste, in der Klassen nach Funktionsbereichen differenziert
sind, kommt der oben geschilderten Hilfestruktur schon relativ nahe. In
der ersten Spalte ist die Funktion, das heißt die Problemstellung, beschrieben. In der zweiten Spalte stehen die hierfür verwendbaren Steuerelemente. In der dritten Spalte folgt eine kurze Beschreibung dieser
Steuerelemente.
Kategorien
Klassenkategorie
Details

Steuerelement,
Benutzersteuerelement und
Formular
Die meisten Klassen im System.Windows.Forms-Namespace sind von
der Control-Klasse abgeleitet. Die Control-Klasse stellt die Basisfunktionen
für alle in einem Form angezeigten Steuerelemente zur Verfügung. Die
Form-Klasse stellt ein Fenster in einer Anwendung dar. Hierzu gehören Dialogfelder, nicht modale Fenster sowie übergeordnete und untergeordnete
MDI-Fenster (Multiple Document Interface). Sie können auch eigene Steuerelemente erstellen, indem Sie von der UserControl-Klasse ableiten.

Menüs und Symbolleisten
Windows Forms enthalten eine umfangreiche Auswahl an Klassen zum Erstellen benutzerdefinierter Symbolleisten und zeitgemäß gestalteter Menüs.
ToolStrip, MenuStrip, ContextMenuStrip und StatusStrip können zum Erstellen von Symbolleisten, Menüleisten, Kontextmenüs und Statusleisten
verwendet werden.

Steuerelemente
Der System.Windows.Forms-Namespace stellt verschiedene Steuerelementklassen bereit, mit denen Sie umfangreiche Benutzeroberflächen erstellen können. Einige Steuerelemente sind für die Dateneingabe in der Anwendung vorgesehen, z. B. das TextBox-Steuerelement und das ComboBox-Steuerelement. Andere Steuerelemente zeigen Anwendungsdaten an,
z. B. das Label-Steuerelement und das ListView-Steuerelement. Der
Namespace stellt außerdem Steuerelemente für das Aufrufen von Befehlen
in der Anwendung bereit, z. B. das Button-Steuerelement. Mit dem
WebBrowser-Steuerelement und verwalteten HTML-Klassen wie HtmlDocument können HTML-Seiten in Windows Forms-Anwendungen angezeigt und geändert werden. Das MaskedTextBox-Steuerelement ist ein erweitertes Steuerelement zur Dateneingabe, mit dem Masken für das automatische Annehmen oder Ablehnen von Benutzereingaben definiert werden können. Darüber hinaus kann das PropertyGrid-Steuerelement zum Erstellen eines eigenen Windows Forms-Designers verwendet werden, der
die zur Entwurfszeit sichtbaren Eigenschaften der Steuerelemente anzeigt.
- Seite 186 -
.NET-Framework & C#.NET

Layout

Daten und Daten- Windows Forms definiert eine umfangreiche Architektur zum Binden an Datenquellen wie Datenbanken und XML-Dateien. Das DataGridView-Steuebindungen
relement stellt eine benutzerdefinierbare Tabelle für das Anzeigen von Daten bereit, deren Zellen, Zeilen, Spalten und Ränder angepasst werden
können. Das BindingNavigator-Steuerelement stellt eine standardisierte
Methode zur Navigation und Arbeit mit Daten in einem Formular dar. BindingNavigator wird häufig zusammen mit dem BindingSource-Steuerelement zur Navigation und Interaktion mit den Datensätzen in einem Formular verwendet.
Das Layout von Steuerelementen in einem Anzeigebereich, z. B. eines Formular oder eines Steuerelements, kann in Windows Forms mithilfe verschiedener wichtiger Klassen gestaltet werden. FlowLayoutPanel bestimmt
das Layout aller darin enthalten Steuerelemente der Reihe nach, und mit
TableLayoutPanel können Sie Zellen und Zeilen für das Layout von Steuerelementen in einem festen Raster festlegen. SplitContainer teilt die Anzeigefläche in zwei oder mehr anpassbare Teile.
- Seite 187 -
.NET-Framework & C#.NET
Funktionsbereiche
Funktion
Textbearbeitung
Steuerelement
TextBox
RichTextBox
Textanzeige
(schreibgeschützt)
Label
LinkLabel
StatusBar
Auswahl aus einer Liste CheckedListBox
ComboBox
ListBox
ListView
NumericUpDown
TreeView
Grafikanzeige
PictureBox
Speichern von Grafiken
ImageList
Festlegen von Werten
CheckBox
CheckedListBox
RadioButton
Trackbar
Datumseinstellung
DateTimePicker
MonthCalendar
Dialogfelder
ColorDialog
FontDialog
OpenFileDialog
Beschreibung
Zeigt zur Entwurfszeit eingegebenen Text an, der
zur Laufzeit von den Benutzern bearbeitet oder
programmgesteuert geändert werden kann.
Text kann im Nur-Text- oder im Rich-Text-Format (RTF) angezeigt werden.
Zeigt Text an, den Benutzer nicht direkt bearbeiten können.
Zeigt Text als Hyperlink an und löst ein Ereignis
aus, wenn die Benutzer auf den Text klicken. In
der Regel stellt der Text eine Verknüpfung zu einem anderen Fenster oder einer Website dar.
Zeigt Informationen über den aktuellen Zustand
der Anwendung in einem Rahmenfenster an,
i. d. R. am unteren Rand eines übergeordneten
Formulars.
Zeigt eine bildlauffähige Liste von Elementen an,
neben denen jeweils ein Kontrollkästchen steht.
Zeigt eine Dropdownliste von Elementen an.
Zeigt eine Liste von Text- und Grafikelementen
(Symbolen) an.
Zeigt Elemente in einer von vier verschiedenen
Ansichten an: Diese Ansichten umfassen nur
Text, Text mit kleinen Symbolen, Text mit großen
Symbolen und eine Detailansicht.
Zeigt eine Liste von Nummernzeichen an, in der
Benutzer mit den Schaltflächen Nach oben bzw.
Nach unten einen Bildlauf durchführen können.
Zeigt eine hierarchische Auflistung von Knotenobjekten an, die aus Text mit optionalen Kontrollkästchen oder Symbolen bestehen können.
Zeigt Grafikdateien, z. B. Bitmaps und Symbole,
in einem Rahmen an.
Dieses Steuerelement dient als Repository für
Bilder. ImageList-Steuerelemente und die darin
enthaltenen Bilder können in nachfolgenden Anwendungen erneut verwendet werden.
Zeigt ein Kontrollkästchen und eine Textbezeichnung an. In der Regel wird dieses Steuerelement
zum Einstellen von Optionen verwendet.
Zeigt eine bildlauffähige Liste von Elementen an,
neben denen jeweils ein Kontrollkästchen steht.
Zeigt eine Schaltfläche an, die aktiviert oder deaktiviert werden kann.
Benutzer können auf einer Skala mit einem Ziehpunkt Werte einstellen.
Zeigt einen grafischen Kalender an, in dem Benutzer ein Datum oder eine Uhrzeit auswählen
können.
Zeigt einen grafischen Kalender an, in dem Benutzer einen Datumsbereich auswählen können.
Zeigt das Dialogfeld zur Farbauswahl an, in dem
Benutzer die Farbe eines Oberflächenelements
einstellen können.
Zeigt ein Dialogfeld an, in dem Benutzer eine
Schriftart und deren Attribute einstellen können.
Zeigt ein Dialogfeld an, in dem Benutzer zu einer
Datei navigieren und diese auswählen können.
- Seite 188 -
.NET-Framework & C#.NET
PrintDialog
PrintPreviewDialog
SaveFileDialog
Menüsteuerelemente
MainMenu
ContextMenu
Befehle
Button
LinkLabel
ToolBar
Gruppierung weiterer
Steuerelemente
Panel
GroupBox
TabControl
Zeigt ein Dialogfeld an, in dem Benutzer einen
Drucker auswählen und dessen Attribute einstellen können.
Zeigt ein Dialogfeld mit der Druckvorschau eines
PrintDocument-Objekts an.
Zeigt ein Dialogfeld an, in dem Benutzer eine Datei speichern können.
Stellt eine Oberfläche zum Erstellen von Menüs
zur Entwurfszeit bereit.
Implementiert ein Kontextmenü, das angezeigt
wird, wenn die Benutzer mit der rechten Maustaste auf ein Objekt klicken.
Mit diesem Steuerelement kann ein Vorgang gestartet, angehalten oder unterbrochen werden.
Zeigt Text als Hyperlink an und löst ein Ereignis
aus, wenn die Benutzer auf den Text klicken. In
der Regel stellt der Text eine Verknüpfung zu einem anderen Fenster oder einer Website dar.
In diesem Steuerelement ist eine Auflistung von
Schaltflächen-Steuerelementen enthalten.
Gruppiert einen Satz von Steuerelementen auf
einem bildlauffähigen Rahmen ohne Bezeichnung.
Gruppiert einen Satz von Steuerelementen (z. B.
Optionsfelder) auf einem nicht bildlauffähigen
Rahmen mit Bezeichnung.
Stellt eine Seite mit Registerkarten zum effizienten Organisieren von und Zugreifen auf gruppierte(n) Objekte(n) bereit.
- Seite 189 -
.NET-Framework & C#.NET
10.3 Elementare Steuerelemente (Klassen)
In diesem Kapitel werden die wichtigsten Klassen für den Aufbau einer
Windows-Form erläutert.
 Als erstes wird das die Button-Klasse sein, die bereits aus dem Eingangsbeispiel bekannt ist. Der Button ist das zentrale Control, um ereignisorientierte Methoden zu implementieren.
 Einfache Ausgaben auf einer Form werden in der Regel über Label –
Klasse realisiert.
 Die Erfassung von Eingaben erfolgt über die Textbox-Klasse.
Zu einem späteren Zeitpunkt werden weitere Ein-und Ausgabe-Controls erläutert.
- Seite 190 -
.NET-Framework & C#.NET
10.3.1 Button-Klasse
Der
ist eines der wichtigsten Controls, das Ereignis-Prozeduren
auslöst. Es wird sehr häufig zur Ablaufsteuerung von Applikationen verwendet.
Eigenschaften
Eigenschaft
BackColor
BackgroundImage
DialogResult
Height
TabIndex
Text
TextAlign
Visible
Width
Beschreibung
Ruft die Hintergrundfarbe für das Steuerelement ab oder legt
diese fest.
Ruft das im Steuerelement angezeigte Hintergrundbild ab oder legt dieses fest.
Ruft einen Wert ab, der beim Klicken auf die Schaltfläche an
das übergeordnete Formular zurückgegeben wird, oder legt
diesen fest.
Ruft die Höhe des Steuerelements ab oder legt diese fest.
Ruft die Aktivierreihenfolge des Steuerelements in dessen
Container ab oder legt diese fest.
Ruft den diesem Steuerelement zugeordneten Text ab oder
legt diesen fest.
Die Texteigenschaft dient der Beschriftung des Button, die allerdings meistens nur im Entwicklungsmodus bei der Oberflächengestaltung gesetzt wird.
Ruft die Ausrichtung des Textes auf dem Schaltflächen-Steuerelement ab oder legt diese fest.
Ruft einen Wert ab, der angibt, ob das Steuerelement angezeigt wird, oder legt diesen fest.
Ruft die Breite des Steuerelements ab oder legt diese fest.
Ereignisse
Ereignis
Beschreibung
Tritt beim Klicken auf das Steuerelement ein.
Das Click-Ereignis ist das am meisten verwendete Ereignis für das AuslöClick-Ereignis sen einer Prozedur. Es bedeutet, dass die an den Button gebundene Prozedur beim Auftreten des Click- Ereignisses beim Button ausgeführt wird.
Der Prozedur-Bezeichner setzt sich daher auch aus dem Namen des Objektes und dem Ereignis zusammen.
Beispiel
private void btnAusgabe_Click(object sender, EventArgs e)
{
lblAusgabe.Text = "Hello World";
}
- Seite 191 -
.NET-Framework & C#.NET
10.3.2 Label-Klasse
Das
dient der Ausgabe von Texten und Zahlen. Die folgenden
Member sind von zentraler Bedeutung:
Eigenschaften
Eigenschaft
Anchor
BackColor
BorderStyle
ForeColor
Height
Text
TextAlign
Visible
Width
Beschreibung
Ruft ab oder legt fest, welche Ränder des Steuerelements an
den Rändern des zugehörigen Containers verankert sind.
Ruft die Hintergrundfarbe für das Steuerelement ab oder legt
diese fest.
Ruft die Rahmenart des Steuerelements ab oder legt diese
fest.
Ruft die Vordergrundfarbe des Steuerelements ab oder legt
diese fest.
Ruft die Höhe des Steuerelements ab oder legt diese fest.
Ruft den diesem Steuerelement zugeordneten Text ab oder
legt diesen fest.
Diese Eigenschaft dient der Darstellung von Zahlen und Text
auf dem Label-Objekt. Zu beachten ist, dass diese Eigenschaft vom Typ String ist und somit bei der Compiler-Einstellung Option Explicit On (eindeutige Deklaration ein) bei numerischen Werten eine Typkonvertierung vorgenommen werden muss.
Ruft die Textausrichtung im Label ab oder legt diese fest.
Ruft einen Wert ab, der angibt, ob das Steuerelement angezeigt wird, oder legt diesen fest.
Ruft die Breite des Steuerelements ab oder legt diese fest.
Beispiel
private void btnAusgabe_Click_1(object sender, EventArgs e)
{
lblAusgabe.Text = "Hello World";
}
- Seite 192 -
.NET-Framework & C#.NET
10.3.3 TextBox-Klasse
Die
dient zur Eingabe von Zahlen und Texten. Die TextboxKlasse ist aber nicht sehr komfortabel, was die Überprüfung von Eingaben
durch Eingabeformate betrifft. Will man hier mehr Komfort, sollte man sich der
RichTextbox-Klasse bedienen.
Eigenschaften
Eigenschaft
MaxLength
Multiline
ReadOnly
ScrollBars
SelectedText
Text
TextLength
Beschreibung
Ruft die maximale Anzahl an Zeichen ab, die Benutzer in
das Textfeld-Steuerelement eingeben oder einfügen können, oder legt diese fest.
Ruft einen Wert ab, der angibt, ob dies ein mehrzeiliges
Textfeld-Steuerelement ist, oder legt diesen fest.
Ruft einen Wert ab, der angibt, ob der im Textfeld enthaltene Text schreibgeschützt ist, oder legt diesen fest.
Ruft die in einem mehrzeiligen TextBox-Steuerelement anzuzeigenden Bildlaufleisten ab oder legt diese fest.
Ruft einen Wert ab, der den derzeitig markierten Text im
Steuerelement angibt, oder legt diesen fest.
Überschrieben.
Diese Eigenschaft speichert die eingegebenen Zahlen und
Text. Zu beachten ist, dass diese Eigenschaft vom Typ
String ist und somit bei der Compiler-Einstellung Option
Explicit On (eindeutige Deklaration ein) bei numerischen
Werten eine Typkonvertierung vorgenommen werden
muss.
Ruft die Länge des Textes im Steuerelement ab.
Methoden()
Eigenschaft
AppendText
Clear
Beschreibung
Fügt Text an den aktuellen Text des Textfeldes an.
Löscht den gesamten Text aus dem Textfeld-Steuerelement.
Mit der Clear-Methode wird die Text-Eigenschaft der TextBox gelöscht.
- Seite 193 -
.NET-Framework & C#.NET
10.4 Übungen - Elementares
Kommen wir nun zum ersten Teil der Übungen zum Namensraum System.Windows.Forms.
10.4.1 Division zweier Zahlen
Programmbeschreibung
Der nachstehend abgebildete Screenshot zeigt ein Programm zur Division
zweier Zahlen.
Bei Eingabe von 0 für den Nenner, soll das Programm mit einer Fehlermeldung beendet werden. Dabei soll die fehlerhafte Eingabe in der TextBox gelöscht werden und der Fokus für die erneute Eingabe auf diese TextBox gesetzt werden.
Hinweise
 Die MessageBox ist eine Klasse, die über statische Methoden zur Erzeugung von Informationsfenstern verfügt.
 Für die Anwendung sind die folgenden Methoden relevant, mit denen bei
einer Falsch-Eingabe beim Nenner die Textbox gelöscht und der Fokus
sofort auf die Textbox des Nenners gesetzt wird:
 TextBox.Clear();
 TextBox.Focus();
 Im Falle einer nicht zulässigen Eingabe beim Nenner muss die Methode
zur Division vorzeitig beendet werden, da ja beim durchführen der Division ansonsten das Programm mit einem Fehler beendet würde. Eine
Methode wird mit der folgenden Anweisung vorzeitig beendet:
 return;
 Das vorzeitige Beenden einer Methode ist vom Beenden einer Applikation
zu unterscheiden. Dieses geschieht durch die Close-Methode der FormKlasse. Die aktuelle Form wird über der Schlüsselwort this angesprochen.
 this.Close();
- Seite 194 -
.NET-Framework & C#.NET
NSD
Vorgehensweise:
 Einlesen der Werte für Zähler und Nenner
 Überprüfung ob der Nenner ungleich 0 ist und Abbruch der Methode für
den Fall Nenner gleich null
 Berechnung des Quotienten
 Ausgabe des Quotienten
- Seite 195 -
.NET-Framework & C#.NET
Code
private void btnRechnen_Click(object sender, EventArgs e) { //Deklarationen double zaehler, nenner, quotient; //Eingabe zaehler = Convert.ToDouble(txbZaehler.Text); nenner = Convert.ToDouble(txbNenner.Text); if (nenner == 0) { MessageBox.Show("Nenner muss ungleich 0 sein!", "Fehler‐Meldung", MessageBoxButtons.OK, MessageBoxIcon.Warning); txbNenner.Clear(); txbNenner.Focus(); return; } //Berechnung quotient = zaehler / nenner; //Ausgabe //lblErgebnis.Text = Convert.ToString(quotient); lblErgebnis.Text = String.Format("{0,12:#,##0.000}", quoti‐
ent); } private void btnEnde_Click(object sender, EventArgs e) { this.Close(); }
- Seite 196 -
.NET-Framework & C#.NET
10.4.2 Rabatt-Berechnung
Programmbeschreibung
Mit der nachstehenden Windows-Anwendung soll das bereits bekannt Problem der Rabattberechnung gelöst werden.
Es gelten für die Berechnung die folgenden Bedingungen:
Umsatz
Rabatt
< 1000,- €
10%
< 2000,- €
20%
< 3000,- €
30%
sonst
40%
Bei Umsatz-Werten, die < oder = 0 sind, erfolgt die nachstehende Fehlermeldung, das Löschen der Eingabe und das Setzen des Fokus auf die EingabeTextBox.
- Seite 197 -
.NET-Framework & C#.NET
NSD
Vorgehensweise
 Einlesen des Wertes für die Variable buttoumsatz
 Überprüfung der Eingabe und beenden der Methode Falls gilt bruttoumsatz<=0
 Gestufte Fallunterscheidung für die Werte <1000, < 2000 und <3000 für
den Bruttoumsatz und Berechnung der Variablen rabatt für die einzelnen
Fälle.
 Berechnung der Variablen nettoumsatz.
 Ausgabe von buttoumsatz, rabatt und nettoumsatz.
- Seite 198 -
.NET-Framework & C#.NET
Code
private void btnRechnen_Click(object sender, EventArgs e) { //Deklarationen double bruttoumsatz, rabatt, nettoumsatz; //Eingabe bruttoumsatz = Convert.ToDouble(txbUmsatz.Text); if (bruttoumsatz <= 0) { MessageBox.Show("Umsatz muss größer 0 sein!", "Fehler‐Meldung", MessageBoxButtons.OK, MessageBoxIcon.Warning); txbUmsatz.Clear(); txbUmsatz.Focus(); return; } //Berechnung if (bruttoumsatz < 1000) rabatt = bruttoumsatz * 0.1; else if (bruttoumsatz < 2000) rabatt = bruttoumsatz * 0.2; else if (bruttoumsatz < 3000) rabatt = bruttoumsatz * 0.3; else rabatt = bruttoumsatz * 0.4; nettoumsatz = bruttoumsatz ‐ rabatt; //Ausgabe lblBrutto.Text = String.Format("{0,12:N}", bruttoumsatz); lblRabatt.Text = String.Format("{0,12:N}", rabatt); lblNetto.Text = String.Format("{0,12:N}", nettoumsatz); } private void btnEnde_Click(object sender, EventArgs e) { this.Close(); }
- Seite 199 -
.NET-Framework & C#.NET
11 DataGridView-Klasse
11.1 DataGridView-Klasse - Überblick
Im Namespace System.Windows.Forms gibt es mit der DataGridView-Klasse
ein für betriebswirtschaftlicher Anwendungen wichtiges Steuerelement. Der
nachstehende Screenshot zeigt eine typsiche Anwendung.
DataGridView-Objekt <=> Array
Das Steuerelemnt DataGridView korrespondiert bei Berechnungen sehr häufig
mit einem Array. Es ist aber wichtig, beides vorn einander zu unterscheiden.
Das DataGridView-Objekt ist für die Anzeige (ggf. auch für die Eingabe) von
Werten in Form einer Matrix. Das Array ist für Berechnungen im Hauptspeicher.
- Seite 200 -
.NET-Framework & C#.NET
11.1.1 Grundlegende Strukturen
Gerade in den Wirtschaftswissenschaften ist die tabellarische Darstellung eine
sehr häufige Form der Präsentation von Daten. In der nachstehenden Abbildung werden in einem DataGridVie-Objekt die Umsatz-Daten nach Filialen
und Quartalen dargestellt sowie die Summen für die Zeilen- und Spalten ausgegeben.
Um die datentechnische Struktur der DataGridView-Klasse besser zu verstehen, müssen die obigen Begriffe geklärt sein:
 Column (Spalte)
Eine Spalte ist ein Objekt, mit dessen Eigenschaften das generelle Erscheinungsbild aller Elemente dieser Spalte festgelegt wird.
 Column-Header
Überschriftenzelle der Spalte (optional)
 Row (Zeile)
Darstellung der Daten
 Row-Header
Beschriftungszelle der Zeile (optional)
 Cell
Eine Zeile besteht aus mehreren Zellen. Was in diesen Zellen ausgegeben werden kann und wie es formatiert wird, wird durch die Column-Eigenschaften festgelegt.
- Seite 201 -
.NET-Framework & C#.NET
11.1.2 Exkurs: Collection-Klasse
Differenzierung
 Collection-Klasse (Altglascontainer)
 Objekte, die die Collection-Klasse sammelt (Flaschen)
Wichtig Differenzierung
Collection als Objekt  Iterms als Objekt
Methoden von Collection-Objekten
 Hinzufügen von Objekten (am Ende anfügen)
 Add - Methode
 AddRange - Methode
 Einfügen an bestimmter Position der Collection-Liste
 Insert-Methode
 Löschen von Objekten
 Clear-Methode
 Remove-Methode
 Anzahl der Objekte in der Collection
 Count-Eigenschaft
 Indexieren bestimmter Elemente
 Item-Eigenschaft
Besonders wichtig
Collection-Objekte werden immer im Plural, Item-Objekte immer im Singular
benannt (Row-Objekte  Rows-Collection).
- Seite 202 -
.NET-Framework & C#.NET
11.1.3 Columns- und Rows-Eigenschaft
Rows- und Colums-Eigenschaften als Collection-Objekte
 Rows-Eigenschaft
 Columns-Eigenschaft
Colums-Eigenschaft in Objekt-Hierarchie
Eine Spalte kann von einem unterchiedlichen Typ sein. Die nachstehenden
Spalten-Klassen sind möglich:
 Button:
DataGridViewButtonColumn
 CheckBox: DataGridViewCheckBoxColumn
 Combobox: DataGridViewComboBoxColumn
 Image:
DataGridViewImageColumn
 Link:
DataGridViewLinkColum
 TextBox:
DataGridViewTextBoxColumn
Weitere Hierarchie-Ebenen der Columns-Klasse
 HeaderCell-Eigenschaft (ColumnHeaderCell-Objekt) mit Eigenschaften
 Styleeigenschaft (CellStyle-Objekt) mit Eigenschaften
 Ausrichtung
 Vordergrundfarbe
 usw.
 DefaultCellStyle-Eigenschaft (CellStyle-Objekt) mit Eigenschaften
 S.oben
- Seite 203 -
.NET-Framework & C#.NET
Rows -Eigenschaft in Objekt-Hierarchie
Struktur:
 Auf der obersten Ebene steht wieder das DataGridView-Objekt.
 In der zweiten Ebene folgt die Rows-Eigenschaft, ein Collection-Objekt,
das die Zeilen verwaltet.
 Diese Zeilen stellen die dritte Ebene dar.
 Eine Zeile verfügt nun wiederum über die Cells-Eigenschaft, die die Zellen einer Zeile verwaltet.
 Diese Zellen stellen die letzte Ebene der Grafik dar. Die Anzahl der Zellen
und deren Erscheinungsbild richtet sich nach den definierten Columns.
- Seite 204 -
.NET-Framework & C#.NET
11.1.4 Aufbau eines DataGridView-Objektes
Anwendung
 Der Anwender gibt die Daten in die Textboxen ein und
 überträgt diese durch Klicken des Button DatenErfassung in das Grid.
 Dabei wird bei jedem Übertragen zuerst eine neue Row im Grid eingerichtet und dann erst die Daten dort gespeichert.
 Jeder neue Datensatz wird also hinten in der Collection der Rows angefügt.
Teilprobleme
 Aufbau des DataGridView-Objekts
 Übertrgaung der Daten
Vorgehensoptionen
- Seite 205 -
.NET-Framework & C#.NET
Manueller, unformatierter Grid-Aufbau
 Event-Handling
 neuer Button sowie Klick-Event
 im Rahmen der Übertragung der Werte von den TextBoxen in das Grid
 Load-Event der Form
Ein Load-Event der Form erzeugt man wie gewohnt durch das Doppelklicken auf die Form. Beachten Sie dabei, dass auf die Form und nicht auf ein
Steuerelement auf der Form klicken dürfen.
private void frmUmsaetze_Load(object sender, EventArgs e) { }
 Code
Name-Eigenschaft des DataGridView-Objekts: grdUmsaetze
 Spalten
 Name der Filiale; Umsatz von vier Quartalen => 5 Spalten
 grdUmsaetze.ColumnCount = 5;
 Zeilen
Die Zeilenanzahl ist in diesem Fall abhängig von der Anzahl der Eingaben und damit vorher nicht bekannt.
 Weitere Einstellungen
Die weiteren Anweisungen haben die die folgenden Wirkungen:
 Spalten-Header ausgeblendet
 Zeilen-Header ausgeblendet
 Option zum Einfügen neuer Zeilen durch den Anwender deaktivieren
 Grid schreibschützen
 Syntax
private void frmUmsaetze_Load(object sender, EventArgs e) { //Gridaufbau grdUmsaetze.ColumnCount = 6; grdUmsaetze.RowCount = 1; grdUmsaetze.ColumnHeadersVisible = false; grdUmsaetze.RowHeadersVisible = false; grdUmsaetze.AllowUserToAddRows = false; grdUmsaetze.ReadOnly = true; }
- Seite 206 -
.NET-Framework & C#.NET
11.1.5 Schematische Darstellung von Rows & Cells
Nachstehend eine schematische Darstellung des DataGridView-Objekts zum
besseren Verständnis des Zugriffs auf Zellen.
Spalte 1
Columns[0]
Spalte 2
Columns[1]
Spalte 3
Columns[2]
Spalte 4
Columns[3]
Spalte 5
Columns[4]
Zeile 1
Rows[0].Cells[0] Rows[0].Cells[1] Rows[0].Cells[2] Rows[0].Cells[3] Rows[0].Cells[4]
Rows[0]
Zeile 2
Rows[1].Cells[0]
Rows[1]
Zeile 3
Rows[2].Cells[0]
Rows[2]
Zugriff auf eine Zelle
Der Zugirff - egal ob lesend oder schreibend - auf die zelle eines DataGridView-Objekts ist die zentrale Funktionalität. Dafür muss
 die entsprechende Row der Rows-Collection und
 die entsprechende Cell (d.h. die Spalte) der Cells-Collection einer Row
angesprochen werden. Diese geschieht durch die Angabe des Indexes in
eckigen Klammern hinter dem entsprechenden Collection-Objekt.
grdUmsaetzte.Rows[0].Cells[1]....
Value-Eigenschaft einer Zelle
Eine Zelle selber ist ein Objekt und besitzt eine Reihe von Membern.
Wert in Zelle ausgeben
grdUmsaetzte.Rows[0].Cells[1].Value = "Test";
Wert aus Zelle lesen
label.Text = grdUmsaetzte.Rows[0].Cells[1].Value;
Achtung!
Die Verwaltung der Rows- und Colums-Items ist nullbasiert!
- Seite 207 -
.NET-Framework & C#.NET
11.1.6 Variabler Zugriff auf Rows & Cells
DataGridView-Objekt - Schematische Darstellung von Rows & Cells
Spalte 1
Columns[0]
Spalte 2
Columns[1]
Spalte 3
Columns[2]
Spalte 4
Columns[3]
Spalte 5
Columns[4]
Zeile 1
Rows[0].Cells[0] Rows[0].Cells[1] Rows[0].Cells[2] Rows[0].Cells[3] Rows[0].Cells[4]
Rows[0]
Zeile 2
Rows[1].Cells[0]
Rows[1]
Zeile 3
Rows[2].Cells[0]
Rows[2]
Variabler Zugriff auf eine Zelle
Durch entspreichende Schleifen für die Variablen zeile und spalte kann jede
beliebige Zelle des Grids adressiert werden.
grdUmsaetzte.Rows[zeile].Cells[spalte].Value = "Test";
Fehlerhafte Lösung
grdUmsaetze.Rows[0].Cells[0].Value = txbFiliale.Text;
grdUmsaetze.Rows[0].Cells[1].Value = txbQ1.Text;
...
Wie konstruiert man aber eine sinnvolle Variable für den Zeilen-Index?
Hinzufügen einer neuen Row im Grid
 grdUmsaetze.RowCount = grdUmsaetze.RowCount + 1;  grdUmsaetze.RowCount++; Variable Adressierung einer Row
 Die Daten sollen in der zuletzt hinzugefügten Row gespeichert werden.
 RowCount-Eigenschaft des DataGridView-Objekts liefert die Anzahl der
Zeilen im Grid.
 Der Index dieser letzten Zeile ist RowCount – 1 (Index ist nullbasiert).
Code
private void btnErfassen_Click(object sender, EventArgs e) { //Deklarationen int dsn; //Prozedur grdUmsaetze.RowCount = grdUmsaetze.RowCount + 1; dsn = grdUmsaetze.RowCount; grdUmsaetze.Rows[dsn ‐ 1].Cells[0].Value = txbFiliale.Text; grdUmsaetze.Rows[dsn ‐ 1].Cells[1].Value = txbQ1.Text; grdUmsaetze.Rows[dsn ‐ 1].Cells[2].Value = txbQ2.Text; grdUmsaetze.Rows[dsn ‐ 1].Cells[3].Value = txbQ3.Text; grdUmsaetze.Rows[dsn ‐ 1].Cells[4].Value = txbQ4.Text; - Seite 208 -
.NET-Framework & C#.NET
11.2 Berechnungen - Grid <=> Array
Der nachfolgende Screenshot zeigt eine Erweiterung der bisher bekannten
Aufgabenstellung. Nach der Erfassung und Übertragung der Daten ins Grid erfolgt die Berechnung der Zeilen- und Spaltensummen. Diese Methode wird
durch das Klicken auf den Button „Berechnungen“ ausgelöst.
Eine direkte Berechnung im Grid ist problematisch und nicht sinnvoll. Wir haben aber bereits solche Berechnungen bei den Konsolenanwendungen in einem Array durchgeführt. Damit sind drei Phase bei der Berechnung zu unterscheiden:
 Dimensionierung des Arrays
 Übertragung der Wert: Grid => Array
 Berechnungen im Array
 Übertragung der Ergebnisse: Array => Grid
Wenn man die Problematik genauer betrachtet, wird klar, dass die Berechnungen im Array bereits bei den Konsolen-Anwendungen behandelt wurden.
- Seite 209 -
.NET-Framework & C#.NET
11.2.1 Dimensionierung des Arrays
Die nachfolgende Grafik veranschaulicht die Strukturen von Grid und Array.
 Es wird eine beliebige Anzahl von Zeilen erfasst - z.B. 10 Zeilen.
 Die RowCount-Eigenschaft hat dann den Wert 10.
 Der Index der letzten Zeile hat dann den Wert 10-1=9.
Zeilenanzahl
 Da alle Zeilen aus dem Grid in das Array übertragen werden sollen
=> Anzahl der Zeilen im Array = Wert der RowCount-Eigenschaft.
 Zusätzlich sind die Spaltensummen zu berechnen
=> Anzahl der Zeilen +1 oder RowCount + 1.
Spaltenanzahl
 Das Grid hat einschließlich der Summenspalte 6 Spalten.
 Allerdings steht in der ersten Spalte die Bezeichnung der Filiale.
 Nicht relevant für die Berechnungen.
 In einem numerischen Array nicht speicherbar.
 Insgesamt benötigen wir damit im Array nur 5 Spalten.
Code
private void btnRechnung_Click(object sender, EventArgs e) { //Deklarationen int anzahl, zeile, spalte; double[,] aryUmsaetze; //Array ensprechend der Rows deklarieren anzahl = grdUmsaetze.Rows.Count; aryUmsaetze = new double[anzahl + 1, 5];
- Seite 210 -
.NET-Framework & C#.NET
11.2.2 Übertragung der Daten: Grid => Array
Nach dem das Array instanziiert ist, können die Daten vom Grid in das Array
übertragen werden.
Übertragung des 1. Wertes
aryUmsaetze[0, 0] = Convert.ToDouble (grdUmsaetze.Rows[0].Cells[1].Value); Achtung: Spalten-Index ist im Grid um 1 höher als im Array
Übertragung aller Werte der 1. Zeile
 Schlechte Lösung
aryUmsaetze[0, 0] = Convert.ToDouble (grdUmsaetze.Rows[0].Cells[1].Value); aryUmsaetze[0, 1] = Convert.ToDouble (grdUmsaetze.Rows[0].Cells[2].Value); …  For-Schleife
//Daten einlesen for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[0, spalte] = Convert.ToDouble( grdUmsaetze.Rows[0].Cells[spalte+1].Value);
- Seite 211 -
.NET-Framework & C#.NET
Übertragung aller Zeilen
 Schlechte Lösung
 nicht effizient
 Anzahl der Zeilen nicht bekannt, daher nicht programmierbar
//Daten einlesen for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[0, spalte] = Convert.ToDouble( grdUmsaetze.Rows[0].Cells[spalte+1].Value);
for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[1, spalte] = Convert.ToDouble( grdUmsaetze.Rows[1].Cells[spalte+1].Value);
…
 For-Schleife
//Daten einlesen for (zeile = 0; zeile <= anzahl ‐ 1; zeile++) for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[zeile, spalte] = Convert.ToDouble (grdUmsaetze.Rows[zeile].Cells[spalte+1].Value);
- Seite 212 -
.NET-Framework & C#.NET
11.2.3 Berechnungen im Array
Die Grafik verdeutlicht noch einmal die zu berechnenden Zellen.
Code
private void btnRechnung_Click(object sender, EventArgs e) { //Deklarationen int anzahl, zeile, spalte; double[,] aryUmsaetze; //Array ensprechend der Rows deklarieren anzahl = grdUmsaetze.Rows.Count; aryUmsaetze = new double[anzahl + 1, 5]; //Daten einlesen for (zeile = 0; zeile <= anzahl ‐ 1; zeile++) for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[zeile, spalte] = Convert.ToDouble (grdUmsaetze.Rows[zeile].Cells[spalte+1].Value); //Zeilensummen for (zeile = 0; zeile <= anzahl ‐ 1; zeile++) for (spalte = 0; spalte <= 3; spalte++) aryUmsaetze[zeile, 4] = aryUmsaetze[zeile, 4] + aryUmsaetze[zeile, spalte]; //Spaltensummen for (spalte = 0; spalte <= 4; spalte++) for (zeile = 0; zeile <= anzahl ‐ 1; zeile++) aryUmsaetze[anzahl, spalte]= aryUmsaetze[anzahl, spalte] + aryUmsaetze[zeile, spalte];
- Seite 213 -
.NET-Framework & C#.NET
11.2.4 Übertragung der Daten: Array => Grid
Bei der Rückübertragung der Daten ins DataGridView-Objekt stellen wir zwei
Varianten vor.
 Übertragung der gesamten Werte des Arrays in das Grid.
 Übertragung der Zeilen- und Spalten-Summen.
Version 1
 Übertragung des 1. Wertes
grdUmsaetze.Rows[0].Cells[1].Value aryUmsaetze[0,0];
 Übertragung aller Werte der 1. Zeile
 Schlechte Variante
grdUmsaetze.Rows[0].Cells[1].Value
grdUmsaetze.Rows[0].Cells[2].Value
grdUmsaetze.Rows[0].Cells[3].Value
grdUmsaetze.Rows[0].Cells[4].Value
grdUmsaetze.Rows[0].Cells[5].Value
aryUmsaetze[0,0];
aryUmsaetze[0,1];
aryUmsaetze[0,2];
aryUmsaetze[0,3];
aryUmsaetze[0,4];
 Effiziente Variante
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[0].Cells[spalte + 1].Value
= aryUmsaetze[0, spalte];
- Seite 214 -
.NET-Framework & C#.NET
 Übertragung aller Zeilen
 Schlechte Variante
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[0].Cells[spalte + 1].Value
= aryUmsaetze[0, spalte];
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[1].Cells[spalte + 1].Value
= aryUmsaetze[1, spalte];
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[2].Cells[spalte + 1].Value
= aryUmsaetze[2, spalte];
...
 Effiziente Variante
for (zeile = 0; zeile <= anzahl; zeile++)
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[zeile].Cells[spalte + 1].Value
= aryUmsaetze[zeile, spalte];
 Summenzeile
//Daten ausgeben
grdUmsaetze.RowCount = grdUmsaetze.RowCount + 1;
for (zeile = 0; zeile <= anzahl; zeile++)
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[zeile].Cells[spalte + 1].Value
= aryUmsaetze[zeile, spalte];
Version 2
//Daten ausgeben
grdUmsaetze.RowCount = grdUmsaetze.RowCount + 1;
//ZeilenSummen
for (zeile = 0; zeile <= anzahl-1; zeile++)
grdUmsaetze.Rows[zeile].Cells[5].Value
= aryUmsaetze[zeile, 4];
//Spaltensummen
for (spalte = 0; spalte <= 4; spalte++)
grdUmsaetze.Rows[anzahl].Cells[spalte + 1].Value
= aryUmsaetze[anzahl, spalte];
- Seite 215 -
.NET-Framework & C#.NET
11.3 Optische Gestaltung des DataGridView-Objekts
Bisher ist die optische Aufbereitung der Ausgabe im Grid nicht sonderlich ansprechend. In den beiden folgenden Abschnitten zeigen wir anhand von zwei
Vorgehensweisen wie ein Grid formatiert werden kann. Die nachstehende Abbildung zeigt das Ziel unserer Überlegungen.
Der erste Weg ist etwas mühseliger, dafür aber übersichtlicher programmiert.
Es werden die einzelnen Spalten formatiert und dann dem Gerät hinzugefügt.
Bei der zweiten Variante arbeiten wir mit Formatierungsvorlagen, die wir dann
jeder Spalte zuweisen.
- Seite 216 -
.NET-Framework & C#.NET
11.3.1 Objekthierarchie
Um die Formatierung des Grids besser zu verstehen, muss die bereits bekannte Objekthierarchie weiter vertieft werden.
Wichtige Eigenschaften
 HeaderText-Eigenschaft
Text der Kopfzelle
 HeaderCell-Eigenschaft
DataGridViewColumnHeaderCell-Objekt,
das die Kopfzelle darstellt mit weiteren Eigenschaften
 DefaultCellStyle-Eigenschaft
DatGridViewCellStyle-Objekt mit weiteren Eigenschaften
- Seite 217 -
.NET-Framework & C#.NET
Grundprinzip
Bisher haben wie die Spalten eines DataGridView-Objekts durch die folgende
simple Anweisung eingerichtet.
private void frmUmsaetze_Load(object sender,EventArgs e)
{
//Gridaufbau
grdUmsaetze.ColumnCount = 6;
Instanziierung von Spalten
private void frmUmsaetze_Load(object sender,EventArgs e)
{
//Deklarationen
DataGridViewTextBoxColumn filiale
= new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn quartal1
= new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn quartal2 =
new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn quartal3
= new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn quartal4
= new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn summe
= new DataGridViewTextBoxColumn();
- Seite 218 -
.NET-Framework & C#.NET
11.3.2 Gestaltung durch CellStyle-Eigenschaften
DefaultCellStyle-Eigenschaften
Formatierung der Daten einer Spalte
 DefaultCellStyle-Eigenschaften = DataGridViewCellStyle-Objekt
Eigenschaften des DataGridViewCellStyle-Objekts:




Alignment-Eigenschaft
Color-Eigenschaft
Format-Eigenschaft
Name-Eigenschaft
Formatierung für die erste und die zweite Spalte
(weitere Spalten analog)
//Spaltenaufbau & Spaltenformate filiale.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft; filiale.DefaultCellStyle.BackColor = Color.LightBlue; filiale.DefaultCellStyle.ForeColor = Color.DarkRed; filiale.Name = "Filiale"; quartal1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight; quartal1.DefaultCellStyle.Format = "#,##0.00 €"; quartal1.DefaultCellStyle.NullValue = null; quartal1.Name = "Quartal1"; - Seite 219 -
.NET-Framework & C#.NET
Formatierung der Header-Zelle der Spalten
 Klassen-Hierarchie der Header-Zelle
 HeaderText-Eigenschaft (Eigenschaft des Column-Objekts)
 HeaderCell.Style.Alignment-Eigenschaft
Zugriff auf das DataGridViewCellStyle-Objekt: HeaderCell.Style. ...
 Code
//Spaltenaufbau & Spaltenformate filiale.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft; filiale.DefaultCellStyle.BackColor = Color.LightBlue; filiale.DefaultCellStyle.ForeColor = Color.DarkRed; filiale.HeaderText = "Standort"; filiale.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; filiale.Name = "Filiale"; quartal1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight; quartal1.DefaultCellStyle.Format = "#,##0.00 €"; quartal1.DefaultCellStyle.NullValue = null; quartal1.HeaderText = "1. Quartal"; quartal1.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; quartal1.Name = "Quartal1"; - Seite 220 -
.NET-Framework & C#.NET
11.3.3 Zugriff über Name-Eigenschaft
Der Name ermöglicht den Zugriff auf eine Spalte bzw. Zelle über diesen Beezichner anstatt des Indexes. Der Code wird damit lesbarer und Verwechselungen werden unwahrscheinlicher.
private void btnErfassen_Click(object sender, EventArgs e) { //Deklarationen int dsn; //Zeilenanzahl erhöhen & DSN ermitteln grdUmsaetze.RowCount = grdUmsaetze.RowCount + 1; dsn = grdUmsaetze.RowCount; //Zellen der Row über Namen ansprechen grdUmsaetze.Rows[dsn ‐ 1].Cells["Filiale"].Value = txbFiliale.Text; grdUmsaetze.Rows[dsn ‐ 1].Cells["Quartal1"].Value = Convert.ToDouble(txbQ1.Text); grdUmsaetze.Rows[dsn ‐ 1].Cells["Quartal2"].Value = Convert.ToDouble(txbQ2.Text); grdUmsaetze.Rows[dsn ‐ 1].Cells["Quartal3"].Value = Convert.ToDouble(txbQ3.Text); grdUmsaetze.Rows[dsn ‐ 1].Cells["Quartal4"].Value = Convert.ToDouble(txbQ4.Text); }
- Seite 221 -
.NET-Framework & C#.NET
11.3.4 Gestaltung durch CellStyle-Objekte
CellStyle-Objekte
Definition von CellStyle-Objekten (Muster) für jedes Format und
Zuweisung dieses Musters zu den Eigenschaften.
Notwendige Formate:
 die erste Datenspalte,
 die übrigen Datenspalten und
 die Kopfzeile,
Instanziierung der Format-Objekte
 grdFormat1 für die erste Spalte,
 grdFormat2 für die übrigen Spalten und
 grdFormatHeader.
Code
private void frmUmsaetze_Load(object sender, EventArgs e) { //Deklarationen //CellStyle‐Objekte DataGridViewCellStyle grdFormat1 = new DataGridViewCellStyle(); DataGridViewCellStyle grdFormat2 = new DataGridViewCellStyle(); DataGridViewCellStyle grdFormatHeader = new DataGridViewCellStyle(); - Seite 222 -
.NET-Framework & C#.NET
Einrichtung der Muster-Formate
//Aufbau der CellStyle‐Objekte grdFormatHeader.BackColor = Color.LightBlue; grdFormatHeader.ForeColor = Color.Black; grdFormatHeader.Alignment = DataGridViewContentAlignment.MiddleCenter; grdFormat1.Alignment = DataGridViewContentAlignment.MiddleLeft; grdFormat1.BackColor = Color.Aquamarine; grdFormat1.ForeColor = Color.DarkRed; grdFormat2.Alignment = DataGridViewContentAlignment.MiddleRight; grdFormat2.Format = "#,##0.00 €"; grdFormat2.ForeColor = Color.DarkMagenta; grdFormat2.BackColor = Color.LightGray; grdFormat2.NullValue = null;
Zuweisung der Formate
//Aufbau der Spalten filiale.DefaultCellStyle = grdFormat1; filiale.HeaderText = "Standort"; filiale.HeaderCell.Style = grdFormatHeader; filiale.Name = "Filiale"; quartal1.DefaultCellStyle = grdFormat2; quartal1.HeaderText = "1. Quartal"; quartal1.HeaderCell.Style = grdFormatHeader; quartal1.Name = "Quartal1"; quartal2.DefaultCellStyle = grdFormat2; quartal2.HeaderText = "2. Quartal"; quartal2.HeaderCell.Style = grdFormatHeader; quartal2.Name = "Quartal2"; - Seite 223 -
.NET-Framework & C#.NET
11.4 Übungen & Fragen
11.4.1 Kapital-Verlauf (Variante 1)
Mit der nachstehenden Anwendung soll der Verlauf eines angelegten Kapitals
veranschaulicht werden. Die Berechnungen solle rekursiv Jahr für Jahr erfolgen. Es sind keine Berechnungen im Array notwendig.
ScreenShot
Code
//Deklarationen DataGridViewTextBoxColumn jahr = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn kapital = new DataGridViewTextBoxColumn(); double startKapital, zinssatz, endKapital; int laufzeit, j; //Spaltenaufbau jahr.DefaultCellStyle.Format = "#0"; jahr.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; jahr.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; jahr.Width = 100; jahr.Name = "Jahr"; - Seite 224 -
.NET-Framework & C#.NET
kapitalDefaultCellStyle.Format = "#,##0.00 €"; kapital.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; kapital.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; ; kapital.Width = 200; kapital.Name = "Kapital"; //Gridaufbau grdKapital.Columns.AddRange(jahr, kapital); grdKapital.RowCount = 1; grdKapital.Width = 300 + 25; grdKapital.RowHeadersVisible = false; grdKapital.AllowUserToAddRows = false; grdKapital.ReadOnly = true; grdKapital.Visible = true; //Werte einlesen startKapital = Convert.ToDouble(txbKapital.Text); zinssatz = Convert.ToDouble(txbZinssatz.Text); laufzeit = Convert.ToInt32 (txbLaufzeit.Text); //Berechnungen und Ausgabe grdKapital.RowCount = laufzeit; endKapital = startKapital; for (j = 0; j < laufzeit; j++) { endKapital = endKapital * (1 + zinssatz / 100); grdKapital.Rows[j].Cells["Jahr"].Value = j + 1; grdKapital.Rows[j].Cells["Kapital"].Value = endKapital; } - Seite 225 -
.NET-Framework & C#.NET
11.4.2 Kapital-Verlauf (Variante 2)
Bei der nachstehenden Variante handelt es sich nur um die optisch aufbereitete Version der obigen Kapitalanlage.
ScreenShot
Code
//Deklarationen DataGridViewCellStyle frmZelleKapital = new DataGrid‐
ViewCellStyle(); DataGridViewCellStyle frmZelleJahr = new DataGridViewCellStyle(); DataGridViewCellStyle frmHeader = new DataGridViewCellStyle(); DataGridViewTextBoxColumn Jahr = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn Kapital = new DataGridViewTextBoxCol‐
umn(); double startKapital, zinssatz, endKapital; int laufzeit, j; //Formate frmZelleKapital.Alignment = DataGridViewContentAlignment.Middle‐
Center; frmZelleKapital.BackColor = Color.AntiqueWhite; frmZelleKapital.ForeColor = Color.Chocolate; frmZelleKapital.Format = "#,##0.00 €"; frmZelleJahr.Alignment = DataGridViewContentAlignment.Middle‐
Center; frmZelleJahr.BackColor = Color.AntiqueWhite; frmZelleJahr.ForeColor = Color.Chocolate; frmZelleJahr.Format = "#0"; - Seite 226 -
.NET-Framework & C#.NET
frmHeader.Alignment = DataGridViewContentAlignment.MiddleCenter; frmHeader.BackColor = Color.Wheat; frmHeader.ForeColor = Color.Black; //Spaltenaufbau Jahr.DefaultCellStyle = frmZelleJahr; Jahr.HeaderText = "Jahr"; Jahr.HeaderCell.Style = frmHeader; Jahr.Width = 100; Jahr.Name = "Jahr"; Kapital.DefaultCellStyle = frmZelleKapital; Kapital.HeaderText = "Kapital"; Kapital.HeaderCell.Style = frmHeader; Kapital.Width = 200; Kapital.Name = "Kapital"; //Gridaufbau grdKapital.Columns.AddRange(Jahr, Kapital); grdKapital.RowCount = 1; grdKapital.Width = 300 + 25; grdKapital.RowHeadersVisible = false; grdKapital.AllowUserToAddRows = false; grdKapital.ReadOnly = true; grdKapital.Visible = true; //Werte einlesen - Seite 227 -
.NET-Framework & C#.NET
11.4.3 Endwert-Methode (Variante 1)
Bei der nachstehenden Anwendung soll noch einmal die bekannt Endwert-Methode der Investitionsrechung als Windows-Anwendung realisiert werden.
ScreenShot
Code
private void btnRechnung_Click(object sender, EventArgs e) { //Deklarationen double investition, cashFlow, zinssatz, endwert, zinsen; int laufzeit, j; //Werte einlesen investition = Convert.ToDouble(txbInvestition.Text); cashFlow = Convert.ToDouble(txbCashFlow.Text); zinssatz = Convert.ToDouble(txbZinsSatz.Text); laufzeit = Convert.ToInt32(txbLaufzeit.Text); //Berechnungen & Ausgabe grdKW.RowCount = laufzeit; endwert = investition * (‐1); for (j = 1; j <= laufzeit; j++) { zinsen = endwert * zinssatz / 100; endwert = endwert + zinsen + cashFlow; grdKW.Rows[j ‐ 1].Cells["clJahr"].Value = j; grdKW.Rows[j ‐ 1].Cells["clCashFlow"].Value = cashFlow; grdKW.Rows[j ‐ 1].Cells["clZinsen"].Value = zinsen; grdKW.Rows[j ‐ 1].Cells["clEndwert"].Value = endwert; } }
- Seite 228 -
.NET-Framework & C#.NET
private void frmEndwert_Load(object sender, EventArgs e) { //Deklarationen DataGridViewTextBoxColumn clJahr = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clCashFlow = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clZinsen = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clEndwert = new DataGridViewTextBoxColumn(); //Spaltenaufbau clJahr.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clJahr.DefaultCellStyle.Format = "#0"; clJahr.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clJahr.Width = 50; clJahr.HeaderText = "Jahr"; clJahr.Name = "clJahr"; clCashFlow.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clCashFlow.DefaultCellStyle.Format = "#,##0.00 €"; clCashFlow.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clCashFlow.Width = 100; clCashFlow.HeaderText = "Cash Flow"; clCashFlow.Name = "clCashFlow"; clZinsen.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clZinsen.DefaultCellStyle.Format = "#,##0.00 €"; clZinsen.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clZinsen.Width = 100; clZinsen.HeaderText = "Zinsen"; clZinsen.Name = "clZinsen"; clEndwert.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clEndwert.DefaultCellStyle.Format = "#,##0.00 €"; clEndwert.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clEndwert.Width = 100; clEndwert.HeaderText = "Endwert"; clEndwert.Name = "clEndwert"; - Seite 229 -
.NET-Framework & C#.NET
//Gridaufbau grdKW.Columns.AddRange(clJahr, clCashFlow, clZinsen, clEndwert); grdKW.RowCount = 1; grdKW.Width = 350 + 25; grdKW.RowHeadersVisible = false; grdKW.AllowUserToAddRows = false; grdKW.ReadOnly = true; grdKW.Visible = true; }
- Seite 230 -
.NET-Framework & C#.NET
11.4.4 Endwert-Methode (Variante 2)
Nachstehend nun wieder die Variante mit der besseren optischen Aufbereitung. Die Änderungen beziehen sich im Wesentlichen auf die Programmierung
in der Form-Load-Methode.
ScreenShot
Code
//Deklarationen DataGridViewCellStyle frmZelleEW = new DataGridViewCellStyle(); DataGridViewCellStyle frmZelleJahr = new DataGridViewCellStyle(); DataGridViewCellStyle frmHeader = new DataGridViewCellStyle(); DataGridViewTextBoxColumn clJahr = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clCashFlow = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clZinsen = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clEndwert = new DataGridViewTextBoxColumn(); //Formate frmZelleEW.Alignment = DataGridViewContentAlignment.MiddleCenter; frmZelleEW.BackColor = Color.AntiqueWhite; frmZelleEW.ForeColor = Color.Chocolate; frmZelleEW.Format = "#,##0.00 €"; - Seite 231 -
.NET-Framework & C#.NET
frmZelleJahr.Alignment = DataGridViewContentAlignment.MiddleCenter; frmZelleJahr.BackColor = Color.AntiqueWhite; frmZelleJahr.ForeColor = Color.Chocolate; frmZelleJahr.Format = "#0"; frmHeader.Alignment = DataGridViewContentAlignment.MiddleCenter; frmHeader.BackColor = Color.Wheat; frmHeader.ForeColor = Color.Black; //Spaltenaufbau clJahr.DefaultCellStyle = frmZelleJahr; clJahr.HeaderText = "Jahr"; clJahr.HeaderCell.Style = frmHeader; clJahr.Width = 50; clJahr.Name = "clJahr"; clCashFlow.DefaultCellStyle = frmZelleEW; clCashFlow.HeaderText = "Cash Flow"; clCashFlow.HeaderCell.Style = frmHeader; clCashFlow.Width = 100; clCashFlow.Name = "clCashFlow"; clZinsen.DefaultCellStyle = frmZelleEW; clZinsen.HeaderText = "Zinsen"; clZinsen.HeaderCell.Style = frmHeader; clZinsen.Width = 100; clZinsen.Name = "clZinsen"; clEndwert.DefaultCellStyle = frmZelleEW; clEndwert.HeaderText = "Endwert"; clEndwert.HeaderCell.Style = frmHeader; clEndwert.Width = 100; clEndwert.Name = "clEndwert"; //Gridaufbau grdKW.Columns.AddRange(clJahr, clCashFlow, clZinsen, clEndwert); grdKW.RowCount = 1; grdKW.Width = 350 + 25; grdKW.RowHeadersVisible = false; grdKW.AllowUserToAddRows = false; grdKW.ReadOnly = true; grdKW.Visible = true; - Seite 232 -
.NET-Framework & C#.NET
11.4.5 Lotto-Gewinn
Bei der nachstehenden Aufgabe soll bei einem Lottogewinn, einer Entnahme
pro Jahr und einem Ertragszins der Kapitalverlauf des Gewinns dargestellt
werden. Das Modell bricht ab, wenn der Gewinn aufgebraucht ist. Von daher
ist darauf zu achten, daß die jährlichen Entnahmen höher als die jährlichen
Zinsen sind.
ScreenShot
Code
private void btnRechnung_Click(object sender, EventArgs e) { //Deklarationen double gewinn, entnahme, zinssatz, endwert, zinsen; int j; //Werte einlesen gewinn = Convert.ToDouble(txbKapital.Text); entnahme = Convert.ToDouble(txbEntnahme.Text); zinssatz = Convert.ToDouble(txbZinsSatz.Text); //Berechnungen & Ausgabe j = 0; endwert = gewinn; while (endwert > 0 & j < 100) { j++; grdKapital.RowCount = grdKapital.RowCount + 1; zinsen = endwert * zinssatz / 100; endwert = endwert + zinsen ‐ entnahme; grdKapital.Rows[j ‐ 1].Cells["clJahr"].Value = j; grdKapital.Rows[j ‐ 1].Cells["clEntnahme"].Value = entnahme; grdKapital.Rows[j ‐ 1].Cells["clZinsen"].Value = zinsen; grdKapital.Rows[j ‐ 1].Cells["clEndwert"].Value = endwert; } }
- Seite 233 -
.NET-Framework & C#.NET
private void Form1_Load(object sender, EventArgs e) { //Deklarationen DataGridViewCellStyle frmZelle = new DataGridViewCellStyle(); DataGridViewCellStyle frmZelleJahr = new DataGridViewCellStyle(); DataGridViewCellStyle frmHeader = new DataGridViewCellStyle(); DataGridViewTextBoxColumn clJahr = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clEntnahme = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clZinsen = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clEndwert = new DataGridViewTextBoxColumn(); //Formate frmZelle.Alignment = DataGridViewContentAlignment.MiddleCenter; frmZelle.BackColor = Color.AntiqueWhite; frmZelle.ForeColor = Color.Chocolate; frmZelle.Format = "#,##0.00 €"; frmZelleJahr.Alignment = DataGridViewContentAlignment.MiddleCenter; frmZelleJahr.BackColor = Color.AntiqueWhite; frmZelleJahr.ForeColor = Color.Chocolate; frmZelleJahr.Format = "#0"; frmHeader.Alignment = DataGridViewContentAlignment.MiddleCenter; frmHeader.BackColor = Color.Azure; frmHeader.ForeColor = Color.Black; //Spaltenaufbau clJahr.DefaultCellStyle = frmZelleJahr; clJahr.HeaderText = "Jahr"; clJahr.HeaderCell.Style = frmHeader; clJahr.Width = 50; clJahr.Name = "clJahr"; clEntnahme.DefaultCellStyle = frmZelle; clEntnahme.HeaderText = "Entnahme"; clEntnahme.HeaderCell.Style = frmHeader; clEntnahme.Width = 100; clEntnahme.Name = "clEntnahme"; - Seite 234 -
.NET-Framework & C#.NET
clZinsen.DefaultCellStyle = frmZelle; clZinsen.HeaderText = "Zinsen"; clZinsen.HeaderCell.Style = frmHeader; clZinsen.Width = 100; clZinsen.Name = "clZinsen"; clEndwert.DefaultCellStyle = frmZelle; clEndwert.HeaderText = "Endwert"; clEndwert.HeaderCell.Style = frmHeader; clEndwert.Width = 100; clEndwert.Name = "clEndwert"; //Gridaufbau grdKapital.Columns.AddRange(clJahr, clEntnahme, clZinsen, clEndwert); grdKapital.RowCount = 1; grdKapital.Width = 350 + 25; grdKapital.RowHeadersVisible = false; grdKapital.AllowUserToAddRows = false; grdKapital.ReadOnly = true; grdKapital.Visible = true; } - Seite 235 -
.NET-Framework & C#.NET
11.4.6 Prämien-Berechung
Mit dem nachstehenden Programm soll Prämien für Mitarbeiter nach der Betriebszugehörigkeit berechnet werden.
Mit dem Button „btnErfassen“ werden die Daten Nachnamen, Betriebszugehörigkeit und Gehalt erfaßt und in das Grid übertragen.
Mit dem Button „btnRchnung“ werden die Daten aus den Spalten Dienstzeit
und Gehalt in ein entsprechendes Array übertragen, die Prämie, die Summe
und die Spaltensumme berechnet und ausgegeben.
ScreenShot
Code
private void btnErfassen_Click(object sender, EventArgs e) { //Deklarationen int z; //Prozedur grdPraemie.RowCount++; z = grdPraemie.RowCount ‐ 1; grdPraemie.Rows[z].Cells["clName"].Value = txbName.Text; grdPraemie.Rows[z].Cells["clJahre"].Value = Convert.ToDouble(txbJahre.Text); grdPraemie.Rows[z].Cells["clGehalt"].Value = Convert.ToDouble(txbGehalt.Text); txbName.Clear(); txbJahre.Clear(); txbGehalt.Clear(); txbName.Focus(); }
- Seite 236 -
.NET-Framework & C#.NET
private void frmPraemie_Load(object sender, EventArgs e) { //Deklarationen DataGridViewCellStyle frmZahlen = new DataGridViewCellStyle(); DataGridViewCellStyle frmName = new DataGridViewCellStyle(); DataGridViewCellStyle frmHeader = new DataGridViewCellStyle(); DataGridViewTextBoxColumn clName = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clJahre = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clGehalt = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clPaemie = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clSumme = new DataGridViewTextBoxColumn(); //Formate frmZahlen.Alignment = DataGridViewContentAlignment.MiddleCenter; frmZahlen.BackColor = Color.AntiqueWhite; frmZahlen.ForeColor = Color.Chocolate; frmZahlen.Format = "#,##0.00"; frmName.Alignment = DataGridViewContentAlignment.MiddleCenter; frmName.BackColor = Color.AntiqueWhite; frmName.ForeColor = Color.Chocolate; frmName.Format = "#0"; frmHeader.Alignment = DataGridViewContentAlignment.MiddleCenter; frmHeader.BackColor = Color.Wheat; frmHeader.ForeColor = Color.Black; //Spaltenaufbau clName.DefaultCellStyle = frmName; clName.HeaderText = "Nachname"; clName.HeaderCell.Style = frmHeader; clName.Width = 100; clName.Name = "clName"; clJahre.DefaultCellStyle = frmZahlen; clJahre.HeaderText = "Dienszeit"; clJahre.HeaderCell.Style = frmHeader; clJahre.Width = 100; clJahre.Name = "clJahre"; clGehalt.DefaultCellStyle = frmZahlen; clGehalt.HeaderText = "Gehalt"; clGehalt.HeaderCell.Style = frmHeader; clGehalt.Width = 100; clGehalt.Name = "clGehalt"; - Seite 237 -
.NET-Framework & C#.NET
clPaemie.DefaultCellStyle = frmZahlen; clPaemie.HeaderText = "Prämie"; clPaemie.HeaderCell.Style = frmHeader; clPaemie.Width = 100; clPaemie.Name = "clPaemie"; clSumme.DefaultCellStyle = frmZahlen; clSumme.HeaderText = "Summe"; clSumme.HeaderCell.Style = frmHeader; clSumme.Width = 100; clSumme.Name = "clSumme"; //Gridaufbau grdPraemie.Columns.AddRange(clName, clJahre, clGehalt, clPaemie, clSumme); grdPraemie.RowCount = 1; grdPraemie.Width = 500 + 25; grdPraemie.RowHeadersVisible = false; grdPraemie.AllowUserToAddRows = false; grdPraemie.ReadOnly = true; grdPraemie.Visible = true; } - Seite 238 -
.NET-Framework & C#.NET
private void btnRechnen_Click(object sender, EventArgs e) { //Deklarationen int z, s, zeilen; double[,] aryPraemie; double prozent; //Dimension bestimmen zeilen = grdPraemie.RowCount; aryPraemie = new double[zeilen + 1, 4]; //Daten einlesen for (z = 1; z <= zeilen; z++) for (s = 1; s <= 2; s++) aryPraemie[z ‐ 1, s ‐ 1] = Convert.ToDouble (grdPraemie.Rows[z ‐ 1].Cells[s].Value); //Prämie & Zeilensumme for (z = 0; z < zeilen; z++) { if (aryPraemie[z, 0] < 1) prozent = 0.05; else if (aryPraemie[z, 0] < 5) prozent = 0.1; else if (aryPraemie[z, 0] < 10) prozent = 0.15; else prozent = 0.2; aryPraemie[z, 2] = aryPraemie[z, 1] * prozent; aryPraemie[z, 3] = aryPraemie[z, 1] + aryPraemie[z, 2]; } //Spaltensummen Gehalt, Prämie, Summe for (s = 1; s <= 3; s++) for (z = 0; z < zeilen; z++) aryPraemie[zeilen, s] = aryPraemie[zeilen, s] + aryPraemie[z, s]; //Ausgabe grdPraemie.RowCount++; for (s = 1; s <= 3; s++) for (z = 0; z <= zeilen; z++) grdPraemie.Rows[z].Cells[s + 1].Value = aryPraemie[z, s]; } - Seite 239 -
.NET-Framework & C#.NET
11.4.7 Kosten- und Gewinnvergleich
Bei der folgenden C#-Anwendung werden die nachstehend Daten zur Abteilung, zum Umsatz und zu den Kosten erfaßt. Es können beliebig viele Abteilungen eingegeben werden.
Beim Klicken des Button „Berechnungen“ werden die relevanten Daten in eine
Array eingelesen, dort die fehlende Werte berechnet und ausgegeben.
Folgende Berechnungen sind durchzuführen:
 Umsatz / Mitarbeiter (Spalte 4 im Grid).
 Ermittlung der Abteilung mit dem höchsten Umsatz je Mitarbeiter
(Spalte 5 im Grid).
 Differenz zwischen Soll- und Ist-Kosten (Spalte 8 im Grid).
 Ausgabe eine Warnung wenn die Abweichung negativ ist (Spalte 9 im
Grid).
 Berechnung der Summen der Spalten 2 3, 4, 6 und 7
Bei der Ausgabe ist die Summenzeile in „Grün“ auszugeben. Die anderen
Spalten sind entsprechend dem obigen ScreenShot aufzubereiten.
- Seite 240 -
.NET-Framework & C#.NET
Überlegungen zu den Berechnungen
Bei Unklarheiten sollten die Berechnung einmal per Hand als eine Alternative
der Problemanalyse durchgeführt werden.
Mit Hilfe des Arrays sollen Berechnungen durchgeführt werden. Damit muß
das Array von einem numerischen Datentyp z.B. Double sein. Das Array muß
alle Daten von der 2. Bis zur 8. Spalte aufnehmen. Die Inhalte der ersten und
der letzten Spalte sind vom Typ String und daher nicht in dem Array darstellbar.
 Verarbeitungsschritte
 Einlesen der Daten vom Grid in das Array beginnend bei Spalte 2 bis
Spalte 7 mit Ausnahme der Spalten 4 und 5.
 Berechnung des Umsatz je Mitarbeiter über alle Abteilungen durch
 Berechnung der Kostendifferenz über alle Abteilungen durch
 Die Warnung muß direkt im Grid ausgegeben werden. Für alle Abteilungen ist die Warnung auszugeben, wenn die berechnete Differenz
negativ ist.
 Ausgabe der Wert vom Array ins Grid.
 Maximaler Umsatz je Mitarbeiter
Hier soll die Abteilung bestimmt werden, die den maximalen Umsatz je Mitarbeiter erreicht hat. Die Vorgehensweise kann an dem folgenden Beispiel
beschrieben werden.
Es existiert ein Stapel mit Karten. Jede Karte ist mit einer laufenden Nummer und einem Zahlenwert versehen. Es soll jetzt aus diesem Stapel, die
Karte mit der größten Zahl ermittelt werden. Führt man das per Hand durch,
so wird man sich einen Zettel für Notizen zur Hand nehmen und den Stapel
mit den Karten durcharbeiten.
Man nimmt die erste Karte und notiert die laufende Nummer und den Wert.
Dann betrachtet man die zweite Karte. Ist der Wert größer als der notierte
Wert, streicht man die alten Notizen und übernimmt die neue laufende Nummer und den neuen Zahlenwert. Ist der Wert auf der Karte geringer als bleiben die alten Werte erhalten.
Am Ende wird auf dem Zettel die laufende Nummer der Karte stehen, die
den höchsten Zahlenwert aufwies.
- Seite 241 -
.NET-Framework & C#.NET
Struktogramm
 Array und Grid aufbauen
 Einlesen der Daten
 Umsatz / Mitarbeiter
 Abteilung mit maximalem Umsatz je Mitarbeiter
 Differenz
- Seite 242 -
.NET-Framework & C#.NET
 Summe
 Ausgabe
 Warnung
- Seite 243 -
.NET-Framework & C#.NET
Code
private void frmKostenRechnung_Load(object sender, EventArgs e) { //Deklarationen DataGridViewTextBoxColumn clAbteilung = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clMitarbeiter = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clUmsatz = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clUmsatzMa = new DataGridViewTextBoxColumn(); … int spaltenBreite; //Aufbau der Spalten stlZahlen.Alignment = DataGridViewContentAlignment.MiddleRight; stlZahlen.Format = "#,##0.00"; spaltenBreite = 90; clAbteilung.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft; clAbteilung.DefaultCellStyle.ForeColor = Color.DarkBlue; clAbteilung.HeaderText = "Abteilung"; clAbteilung.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clAbteilung.Width = spaltenBreite; … clMitarbeiter.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clMitarbeiter.HeaderText = "Mitarbeiter"; clMitarbeiter.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clMitarbeiter.Width = spaltenBreite; clUmsatz.DefaultCellStyle = stlZahlen; clUmsatz.HeaderText = "Umsatz"; clUmsatz.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clUmsatz.Width = spaltenBreite; ... //Gridaufbau grdKLR.Columns.AddRange(clAbteilung, clMitarbeiter, clUmsatz, clUmsatzMa, clRanking, clKostenSoll, clKostenIst, clAbweichung, clWarnung); grdKLR.AllowUserToAddRows = false; … grdKLR.Width = grdKLR.Columns.Count * spaltenBreite + 30; }
- Seite 244 -
.NET-Framework & C#.NET
private void btnErfassen_Click(object sender, EventArgs e) { //Deklarationen int dsn; //Prozedur grdKLR.Rows.Add(); dsn = grdKLR.Rows.Count ‐ 1; grdKLR.Rows[dsn].Cells[0].Value = txbAbteilung.Text; grdKLR.Rows[dsn].Cells[1].Value = txbMitarbeiter.Text; grdKLR.Rows[dsn].Cells[2].Value = Convert.ToDouble(txbUmsatz.Text); grdKLR.Rows[dsn].Cells[5].Value = Convert.ToDouble(txbKostenSoll.Text); grdKLR.Rows[dsn].Cells[6].Value = Convert.ToDouble(txbKostenIst.Text); } private void btnBerechnung_Click(object sender, EventArgs e) { //Deklarationen double[,] aryKLR; int anzahl, z, s, maxZeile; double maxWert; //Aufbau des Arrays & Summenzeile Grid anzahl = grdKLR.Rows.Count; aryKLR = new double[anzahl + 1, 7]; grdKLR.Rows.Add(); //Einlesen der Daten for (z = 0; z <= anzahl ‐ 1; z++) for (s = 1; s <= 6; s++) if (s != 3 & s != 4) aryKLR[z, s ‐ 1] = Convert.ToDouble (grdKLR.Rows[z].Cells[s].Value); //Umsatz / Mitarbeiter & Ranking for (z = 0; z <= anzahl ‐ 1; z++) aryKLR[z, 2] = aryKLR[z, 1] / aryKLR[z, 0]; - Seite 245 -
.NET-Framework & C#.NET
maxWert = 0; maxZeile = 0; for (z = 0; z <= anzahl ‐ 1; z++) if (aryKLR[z, 2] > maxWert) { maxWert = aryKLR[z, 2]; maxZeile = z; } aryKLR[maxZeile, 3] = 1; //Differenz for (z = 0; z <= anzahl ‐ 1; z++) { aryKLR[z, 6] = aryKLR[z, 4] ‐ aryKLR[z, 5]; } //Summen for (s = 0; s <= 5; s++) if (s != 3) for (z = 0; z <= anzahl ‐ 1; z++) aryKLR[anzahl, s] = aryKLR[anzahl, s] + aryKLR[z, s]; //Ausgabe grdKLR.Rows[anzahl].Cells[0].Value = "Summe"; for (z = 0; z <= anzahl; z++) for (s = 0; s <= 6; s++) { grdKLR.Rows[z].Cells[s + 1].Value = aryKLR[z, s]; if (z == anzahl) grdKLR.Rows[z].Cells[s + 1].Style.ForeColor = Color.DarkGreen; } //Warnung for (z = 0; z <= anzahl; z++) if (aryKLR[z, 6] < 0) grdKLR.Rows[z].Cells[8].Value = "Warnung"; }
- Seite 246 -
.NET-Framework & C#.NET
11.4.8 Break-Even-Analyse
Das nachstehende C#-Programm dient der Darstellung einer Break-Even-Analyse. Dabei werden für zwei Investitionen jeweils die fixen und die variablen
Kosten eingegeben. Es liegt damit eine lineare Kostenfunktion des Typs
∗
zugrunde.
Die Kapazitätsgrenze ist der Wert, bis zu dem die Berechnungen durchgeführt
werden; die Schrittweite legt den Zuwachs zur nächst höheren Ausbringungsmenge fest.
Bei der Ausgabe soll die niedrigere der beiden Werte in Grün angegeben werden.
- Seite 247 -
.NET-Framework & C#.NET
Struktogramm
Code
private void Form1_Load(object sender, EventArgs e) { //Deklarationen DataGridViewTextBoxColumn clMenge = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clMaschine1 = new DataGridViewTextBoxColumn(); DataGridViewTextBoxColumn clMaschine2 = new DataGridViewTextBoxColumn(); //Gridaufbau clMenge.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; clMenge.DefaultCellStyle.Format = "#,##0"; clMenge.HeaderCell.Value = "Menge"; clMenge.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clMenge.Width = 100; clMaschine1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight; clMaschine1.DefaultCellStyle.Format = "#,##0.00 €"; clMaschine1.HeaderCell.Value = "Maschine 1"; clMaschine1.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; clMaschine1.Width = 150; … grdKosten.Columns.AddRange(clMenge, clMaschine1, clMaschine2); grdKosten.RowHeadersVisible = false; grdKosten.AllowUserToAddRows = false; grdKosten.AllowUserToDeleteRows = false; grdKosten.ReadOnly = true; grdKosten.Width = 430; grdKosten.Visible = false; }
- Seite 248 -
.NET-Framework & C#.NET
private void btnBerechnungen_Click(object sender, EventArgs e) { //Deklarationen double kf1, kv1, kf2, kv2, kapazitaet, kg1, kg2; int step, menge; //Einlesen der Werte kf1 = Convert.ToDouble(txbKf_1.Text); kv1 = Convert.ToDouble(txbKv_1.Text); kf2 = Convert.ToDouble(txbKf_2.Text); kv2 = Convert.ToDouble(txbKv_2.Text); kapazitaet = Convert.ToDouble(txbMenge.Text); step = Convert.ToInt32(txbSchrittweite.Text); //Berechnung & Ausgabe grdKosten.Rows.Clear(); for (menge = 0; menge <= kapazitaet; menge = menge + step) { //Berechnungen kg1 = kv1 * menge + kf1; kg2 = kv2 * menge + kf2; //Ausgabe grdKosten.Rows.Add(); grdKosten.Rows[grdKosten.Rows.Count‐1].Cells[0].Value = menge; grdKosten.Rows[grdKosten.Rows.Count‐1].Cells[1].Value = kg1; grdKosten.Rows[grdKosten.Rows.Count‐1].Cells[2].Value = kg2; if (kg1 < kg2) grdKosten.Rows[grdKosten.Rows.Count‐1].Cells[1].Style. ForeColor = Color.DarkGreen; else grdKosten.Rows[grdKosten.Rows.Count ‐ 1].Cells[2].Style. ForeColor = Color.DarkGreen; } } - Seite 249 -
.NET-Framework & C#.NET
11.4.9 Verteilung von Gemeinkosten
Mit der nachstehenden Anwendung werden die Gemeinkosten für Heizung
und Verwaltung auf die Abteilungen verteilt. Dabei werden die Heizkosten proportional zu Fläche der Abteilung und die Verwaltungskosten linear aufgeteilt.
Mit dem Button „Erfassen“ werden die Abteilungsdaten im Grid erfaßt.
Beim Klicken des Button „Berechnungen“ werden die Gemeinkosten eingelesen und die relevanten Daten aus dem Grid in ein Array übertragen. Im Array
werden dann die nachstehenden Berechnungen durchgeführt und diese Werte
im Grid ausgegeben.
- Seite 250 -
.NET-Framework & C#.NET
Struktogramm
 Gridaufbau und Array
 Einlesen der Daten
 Summe der Fläche
 Verteilungsschlüssel und Verteilung
 Zeilensumme
 Ausgabe
- Seite 251 -
.NET-Framework & C#.NET
Code
private void btnBerechnung_Click(object sender, EventArgs e) { //Deklarationen double heizung, verwaltung, anteilHeizung, anteilVerwaltung; double[,] aryGMK; int anzahl, z, s; //Aufbau Arrray & Grid um Summenzeile erweitern anzahl = grdGMK.Rows.Count; aryGMK = new Double[anzahl + 1, 4]; grdGMK.Rows.Add(); //Einlesen der Daten heizung = Convert.ToDouble(txbHeizung.Text); verwaltung = Convert.ToDouble(txbVerwaltung.Text); for (z = 0; z <= anzahl ‐ 1; z++) aryGMK[z, 0] = Convert.ToDouble (grdGMK.Rows[z].Cells[1].Value); //Summe der Fläche for (z = 0; z <= anzahl ‐ 1; z++) aryGMK[anzahl, 0] = aryGMK[anzahl, 0] + aryGMK[z, 0]; //Verteilungsschlüssel anteilHeizung = heizung / aryGMK[anzahl, 0]; anteilVerwaltung = verwaltung / anzahl; //Kostenverteilung for (z = 0; z <= anzahl ‐ 1; z++) { aryGMK[z, 1] = aryGMK[z, 0] * anteilHeizung; aryGMK[z, 2] = anteilVerwaltung; } //Zeilensummen for (z = 0; z <= anzahl ‐ 1; z++) for (s = 1; s <= 2; s++) aryGMK[z, 3] = aryGMK[z, 3] + aryGMK[z, s]; //Ausgabe for (z = 0; z <= anzahl ‐ 1; z++) for (s = 1; s <= 3; s++) grdGMK.Rows[z].Cells[s + 1].Value = aryGMK[z, s]; //Ausgabe der letzten Zeile grdGMK.Rows[anzahl].Cells[1].Value = aryGMK[anzahl, 0]; grdGMK.Rows[anzahl].Cells[2].Value = heizung; grdGMK.Rows[anzahl].Cells[3].Value = verwaltung; grdGMK.Rows[anzahl].Cells[4].Value = heizung + verwaltung; - Seite 252 -
Herunterladen