Walter Doberenz, Thomas Gewinnus Visual C# 2008 Kochbuch ISBN-10: 3-446-41442-8 ISBN-13: 978-3-446-41442-6 Vorwort Weitere Informationen oder Bestellungen unter http://www.hanser.de/978-3-446-41442-6 sowie im Buchhandel.
Vorwort Vorwort Liebe Leserin, lieber Leser, Sie halten gerade die dritte Auflage unseres im Jahr 2003 erstmalig erschienenen Visual C#- Kochbuchs in den Händen. Gegenüber dem Vorgängertitel zur Version 2005 wurde es gründlich überarbeitet und von verstaubten Inhalten befreit, um Platz für die zahlreichen Neuerungen der Version 2008 (LINQ, WPF...) zu schaffen. Eingeflossen sind weiterhin die kritischen Hinweise unserer Leser zu den bis jetzt von uns veröffentlichten C#-Büchern, die Erfahrungen von Lehrgängen und Workshops und, last but not least, die gesammelten Erkenntnisse unserer eigenen intensiven Programmiertätigkeit. All das findet seinen Niederschlag in mehr als 100 verbesserten und neuen Rezepten, sodass der Umfang dieses Buchs um mehr als 300 Seiten gegenüber seinem Vorgänger angewachsen ist! Wie es der Titel bereits suggeriert, besteht der Inhalt aus einer Fülle von "Rezepten", die Ihnen sowohl beim Einstieg in Visual C# 2008 als auch bei der Bewältigung Ihrer alltäglichen Programmieraufgaben helfen sollen. Bis auf wenige Ausnahmen sind alle Rezepte lauffähige Programme mit eigener Bedienoberfläche, die sofortiges Ausprobieren und eigene Experimente mit "Aha-Effekt" ermöglichen, wobei sich der inhaltliche Bogen vom einfachen Tipp & Trick für den Einsteiger bis hin zur komplexen Profi-Applikation spannt. Hat ein solches Kochbuch im Internet-Zeitalter überhaupt noch eine Chance, wo man doch über Suchmaschinen auf (fast) jede Frage Dutzende von Lösungen gratis frei Haus erhält? Die Antwort ist heute, mehr denn je, ein eindeutiges Ja. Gerade in der ausufernden Flut von Lösungen, die über das Internet abrufbar sind, liegt ein gravierendes Problem, denn es wird dadurch immer schwieriger, die Spreu vom Weizen zu trennen. Wie immer haben wir uns auch in diesem Buch bemüht, nur qualitativ hochwertige Lernbeispiele und Problemlösungen zu bringen, ohne dabei das zu wiederholen, was Ihnen die zu Visual C# 2008 bzw. Visual Studio 2008 allgemein verfügbaren Quellen ohnehin schon bieten. Zum Buch-Inhalt Die fast 500 Rezepte des Kochbuchs sind in 16 Themengruppen übersichtlich angeordnet und mit treffsicheren Titeln ausgestattet. Der Index sollte ein Übriges dazu beitragen, schnell an die gewünschten Informationen zu kommen. Kapitel 1 ist speziell für den Programmier-Einsteiger gedacht. Es enthält einen kleinen Crashkurs, in welchem in mehreren sorgfältig aufeinander abgestimmten Rezepten wichtige Grundlagen der Sprache C# allgemeinverständlich erläutert werden.
20 Vorwort Kapitel 2 widmet sich speziellen Features der Sprache C#, wie z.b. Stringverarbeitung, Parameterübergabe, Delegates und LINQ-Erweiterungen. Kapitel 3 enthält Rezepte zur optimalen Programmierung von Windows Forms Oberflächen und befasst sich mit den Besonderheiten der wichtigsten Steuerelemente. Kapitel 4 enthält zahlreiche Rezepte zu den verschiedensten Problemen, wie sie bei der Grafikprogrammierung auftreten. Kapitel 5 ist dem Problemkreis Drucken/Druckeransteuerung gewidmet, wie er immer wieder Gesprächsstoff in Entwickler-Foren ist. Kapitel 6 enthält verschiedene Rezepte zu OOP-Grundlagen und zur Komponentenentwicklung. Kapitel 7 umfasst eine unterhaltsame Serie von aufeinander abgestimmten Beispielen, die bis in die gehobenen Regionen der OOP führen (Microsoft Event Pattern!). Kapitel 8 befasst sich mit dem Dateizugriff unter.net. Kapitel 9 enthält zahlreiche Rezepte rund um den Problemkreis XML. Kapitel 10 widmet sich verschiedensten Aspekten des Datenbankzugriffs unter ADO.NET. Kapitel 11 enthält einige nützliche Rezepte, die den Einstieg in die relativ neue Technologie der Microsoft Reporting Services erleichtern sollen. Kapitel 12 umfasst zahlreiche Rezepte, die (fast) alle Facetten der Web-Programmierung unter ASP.NET ausleuchten. Kapitel 13 bezieht sich auf Rezepte zur neuen WPF-Technologie, einem der Highlights von Visual Studio 2008. Kapitel 14 enthält eine Sammlung von Rezepten für den Zugriff auf wichtige Funktionen des Windows-Betriebssystems. Kapitel 15 kapselt ein Sammelsurium von Rezepten zu Themen, die sich in keines der anderen Kapitel sinnvoll einordnen ließen, z.b. Setup-Projekte und Hilfedateien. Kapitel 16 bildet den krönenden Abschluss des Kochbuchs. In praxistauglichen Beispielapplikationen werden verschiedene Programmiertechniken im Zusammenhang demonstriert. Inhalt der Buch-DVD Die zu diesem Buch mitgelieferte DVD enthält den vollständigen Quellcode aller Rezepte. Auch alle benötigten Beispieldatenbanken sind mehrfach enthalten. Alle Rezepte wurden unter Windows XP und Windows Vista auf Funktionsfähigkeit getestet.
Vorwort 21 Für den Einsteiger hier noch einige weitere Hinweise, die wir aufgrund von Erfahrungen mit unseren C#-Vorgängertiteln diesmal nicht vergessen wollen: Sie sollten natürlich Visual Studio 2008 auf Ihrem PC installiert haben. Für einige Beispiele ist auch eine Installation von SQL Server 2005 (SQLEXPRESS) erforderlich. In der Regel sind alle von der Festplatte gestarteten Beispiele sofort lauffähig, da die Datenbanken (sowohl für MS Access als auch für MS SQL Server) meistens direkt in das Projektverzeichnis kopiert wurden, wodurch Probleme mit absoluten Pfadangaben entfallen. Bei verteilten Anwendungen, insbesondere bei den Beispielen zu ASP.NET und XML-Webdiensten, ist besondere Aufmerksamkeit geboten (Reihenfolge der Installation der Clientund Server-Komponenten beachten, siehe beigefügte Liesmich-Dateien). HINWEIS: Zusätzlich ist auf der DVD die deutsche Version der Visual Studio 2008 Express Edition enthalten, mit welcher die Mehrheit der Rezepte dieses Buchs nachvollzogen werden kann. Kontakt zu den Autoren Nobody is perfect, und so können es auch die Autoren nicht ausschließen, dass sich auf den 1200 Seiten dieser oder jener Fehler eingeschlichen hat oder dass etwas Wichtiges einfach vergessen wurde. HINWEIS: Auch wenn Sie das "Haar in der Suppe" gefunden haben sollten wir sind für alle sachlich fundierten Hinweise und Kritiken dankbar! Richten Sie Ihr Feedback bitte an folgende Adresse: autoren@doko-buch.de Aktuelle Hinweise, Fehlerberichtigungen etc. finden Sie auf unserer Homepage: www.doko-buch.de Wir wünschen Ihnen neben dem notwendigen Stehvermögen auch zahlreiche freudige "Aha"-Erlebnisse auf Ihrem Weg zum erfolgreichen C#-Programmierer! Walter Doberenz und Thomas Gewinnus Altenburg und Frankfurt/O., im April 2008
Walter Doberenz, Thomas Gewinnus Visual C# 2008 Kochbuch ISBN-10: 3-446-41442-8 ISBN-13: 978-3-446-41442-6 Leseprobe Weitere Informationen oder Bestellungen unter http://www.hanser.de/978-3-446-41442-6 sowie im Buchhandel.
R8.3 Alle Dateien auflisten 465 R8.3 Alle Dateien auflisten Das vorliegende Rezept demonstriert, wie man mit der GetFiles-Methode zu einem gegebenen Verzeichnis alle Unterverzeichnisse ermitteln und in einem FileInfo-Array ablegen kann. Oberfläche Ein Formular mit einer ListBox genügt. Quellcode... using System.IO; public partial class Form1 : Form Die Anzeigeprozedur wird gleich zu Beginn (im Konstruktor von Form1) aufgerufen: public Form1() InitializeComponent(); listallfiles("c:\\", listbox1); Als Parameter werden der Anzeigeprozedur das übergeordnete Verzeichnis (hier Root-Directory) und eine ListBox übergeben: public void listallfiles(string pfad, ListBox lb) Ein DirectoryInfo-Objekt anlegen: DirectoryInfo mydir = new DirectoryInfo(pfad); Array zum Speichern der Dateien anlegen: FileInfo[] myfiles; Alle im Verzeichnis enthaltenen Dateien ermitteln und das Array füllen: myfiles = mydir.getfiles(); Das Array durchlaufen und die Dateinamen zur ListBox hinzufügen: for (int i = 0; i < myfiles.length; i++) lb.items.add(myfiles[i].name);
466 Kapitel 8: Dateien/Verzeichnisse Test Alle im Verzeichnis C:\ enthaltenen Dateien werden sofort nach Programmstart aufgelistet: R8.4 Die GetFileSystemInfos-Methode verwenden Als Alternative zu den Vorgängerrezepten R8.2 und R8.3 zeigen wir hier eine weitere Möglichkeit, alle in einem Verzeichnis enthaltenen Unterverzeichnisse und Dateien aufzulisten. Oberfläche Ein Formular mit einer ListBox soll uns genügen. Quellcode... using System.IO; public partial class Form1 : Form public Form1() InitializeComponent(); Auch in diesem Testprogramm ist die Root-Directory Gegenstand der Untersuchungen: listfilesysteminfos("c:\\", listbox1); Der Anzeigemethode werden ein Verzeichnispfad und eine ListBox-Referenz übergeben: public void listfilesysteminfos(string pfad, ListBox lb)
R8.4 Die GetFileSystemInfos-Methode verwenden 467 Auch hier beginnt alles mit einem DirectoryInfo-Objekt: DirectoryInfo mydir = new DirectoryInfo(pfad); Jetzt werden alle dazugehörigen Einträge ermittelt: FileSystemInfo[] fsi = mydir.getfilesysteminfos(); Zunächst den vollständigen Verzeichnispfad anzeigen: lb.items.add(mydir.fullname);... dann alle Unterverzeichnisse und Dateien: foreach (FileSystemInfo info in fsi) lb.items.add(info.name); Test Nach Programmstart werden alle in der Root des Laufwerks C: enthaltenen Unterverzeichnisse und Dateien angezeigt:
468 Kapitel 8: Dateien/Verzeichnisse R8.5 Die Path-Klasse kennen lernen Eine Alternative zur File-Klasse ist die Path-Klasse. In diesem Rezept wollen wir einige ihrer zahlreichen (statischen) Methoden demonstrieren. Oberfläche Auch hier genügt uns (neben dem Startformular Form1) eine ListBox. Quellcode... using System.IO; public partial class Form1 : Form public Form1() InitializeComponent(); Beim Aufruf der Testmethode sind der vollständige Namen einer vorhandenen Datei und eine ListBox-Referenz zu übergeben: getinfos("c:\\temp\\test.txt", listbox1); Die Testmethode: public void getinfos(string datname, ListBox lb) lb.items.add("verzeichnis : " + Path.GetDirectoryName(datName)); lb.items.add("dateiname : " + Path.GetFileName(datName)); lb.items.add("dateiname ohne Extension : " + Path.GetFileNameWithoutExtension(datName)); lb.items.add("dateiextension : " + Path.GetExtension(datName)); lb.items.add("rootverzeichnis : " + Path.GetPathRoot(datName)); lb.items.add("temporäres Verzeichnis : " + Path.GetTempPath()); lb.items.add("neues Tempfile : " + Path.GetTempFileName()); Test Voraussetzung für einen erfolgreichen Test ist das Vorhandensein einer Datei c:\temp\test.txt.
R8.6 Verzeichnis- und Datei-Informationen gewinnen 469 HINWEIS: Vorsicht ist geboten, denn die meisten Member der Path-Klasse wirken nicht mit dem Dateisystem zusammen und überprüfen deshalb nicht, ob die durch eine Pfadzeichenfolge angegebene Datei auch tatsächlich vorhanden ist! R8.6 Verzeichnis- und Datei-Informationen gewinnen Dieses Rezept zeigt Ihnen nicht nur den Einsatz der DirectoryInfo- und FileInfo-Klasse, sondern auch weiteres nützliches Handwerkszeug, wie z.b. die sinnvolle Verknüpfung zweier ListBox- Komponenten. Oberfläche Auf Form1 platzieren wir eine TextBox-, zwei ListBox- und zwei große Label- Komponenten im 3D-Outfit (siehe Laufzeitabbildung). Quelltext... using System.IO; public partial class Form1 : Form... Globale Deklarationen auf Form1-Ebene: private string myroot = "C:/"; private string mydirname, myfilename; private const char CrLf = (char) 10; // übergeordnetes Verzeichnis // aktuelles Unterverzeichnis bzw. Datei // Zeilenumbruch Beim Laden werden zunächst alle Unterverzeichnisse von C:/ angezeigt: private void Form1_Load(object sender, EventArgs e) textbox1.text = myroot;
470 Kapitel 8: Dateien/Verzeichnisse showdirectories(); Die folgende Methode zeigt alle zu myroot untergeordneten Verzeichnisse an: private void showdirectories() DirectoryInfo[] mydirectories; // Array zum Speichern der Unterverzeichnisse Erzeugen eines neuen DirectoryInfo-Objekts, welches auf das Rootverzeichnis zeigt: DirectoryInfo mydirectory = new DirectoryInfo(myRoot); Alle Unterverzeichnisse ermitteln und abspeichern (vorher Anzeige löschen): mydirectories = mydirectory.getdirectories(); listbox1.items.clear(); Alle Verzeichnisse durchlaufen... for (int i = 0; i < mydirectories.length; i++)... und Verzeichnisnamen anzeigen: listbox1.items.add(mydirectories[i].name); Der erste Eintrag in der Verzeichnis-ListBox wird selektiert, dadurch wird das SelectedIndex- Changed-Event ausgelöst: listbox1.selectedindex = 0; Synchronisieren aller Dateien in der rechten ListBox mit dem selektierten Verzeichnis und Anzeige der Verzeichnis-Informationen: private void listbox1_selectedindexchanged(object sender, EventArgs e) DirectoryInfo mydirectory; // aktuelles Verzeichnis string dirinfo = String.Empty; FileInfo[] myfiles; // Array für alle Dateiinformationen listbox2.items.clear(); // aktuellen Inhalt löschen Neues DirectoryInfo-Objekt aufgrund des selektierten ListBox-Eintrags erzeugen: mydirname = listbox1.selecteditem.tostring() + "/"; mydirectory = new DirectoryInfo(myRoot + mydirname); Verzeichnis-Infos zusammensetzen: dirinfo += "Pfad: " + mydirectory.fullname + CrLf; dirinfo += "Erstellungsdatum: " + mydirectory.creationtime + CrLf; dirinfo += "Attribute: " + mydirectory.attributes.tostring() + CrLf; label1.text = dirinfo;
R8.6 Verzeichnis- und Datei-Informationen gewinnen 471 Alle im Verzeichnis enthaltenen Dateien dem FileInfo-Array zuweisen: try myfiles = mydirectory.getfiles(); File-Array durchlaufen und die Dateien zur ListBox hinzufügen: if (myfiles.length > 0) for (int i = 0; i < myfiles.length; i++) listbox2.items.add(myfiles[i].name); Ersten Eintrag in der Datei-ListBox selektieren, dadurch wird deren SelectedIndexChanged- Event ausgelöst: listbox2.selectedindex = 0; catch (Exception ex) MessageBox.Show(ex.Message); Zweck des folgenden Eventhandlers ist es, den Inhalt des Labels "Datei-Informationen" zu aktualisieren: private void listbox2_selectedindexchanged(object sender, EventArgs e) FileInfo myfile; string fileinf = String.Empty; Die Dateinamen zuweisen: myfilename = listbox2.selecteditem.tostring(); Neues File-Objekt erzeugen: myfile = new FileInfo(myRoot + mydirname + myfilename); Datei-Infos zusammensetzen und anzeigen: fileinf += "Verzeichnis: " + myfile.directoryname + CrLf; fileinf += "Erstellungsdatum: " + myfile.creationtime + CrLf; fileinf += "Größe: " + myfile.length + " Byte" + CrLf; fileinf += "Letzter Zugriff: " + myfile.lastaccesstime + CrLf; fileinf += "Attribute: " + myfile.attributes.tostring() + CrLf; label2.text = fileinf;
472 Kapitel 8: Dateien/Verzeichnisse Wenn Sie das übergeordnete Verzeichnis in textbox1 eingetragen haben, kann die Enter-Taste ausgewertet werden um die Eingabe abzuschließen: private void textbox1_keyup(object sender, KeyEventArgs e) if (e.keycode == Keys.Enter) myroot = textbox1.text; Mit einem kleinen Trick den letzten Slash ergänzen, falls notwendig: if (!myroot.endswith("/")) myroot += "/"; showdirectories(); Test Bei Programmstart erscheinen zunächst in der linken ListBox alle Unterverzeichnisse zur Root C:/. Klicken Sie nun auf ein Unterverzeichnis, um sich in der rechten ListBox die darin enthaltenen Dateien anzeigen zu lassen. HINWEIS: Wenn Sie sich in der Verzeichnishierarchie von oben nach unten weiterbewegen wollen, müssen Sie das Hauptverzeichnis in der TextBox per Hand ergänzen und die Eingabe mit der Enter-Taste abschließen.
R8.7 Änderungen im Dateisystem überwachen 473 Ziemlich häufig kann es aber auch (insbesondere unter den restriktiven Sicherheitseinstellungen von Windows Vista) zu folgender Fehlermeldung kommen: R8.7 Änderungen im Dateisystem überwachen Dieses Rezept zeigt, wie Sie unter Verwendung der Klasse FileSystemWatcher das Dateisystem beobachten können. Wichtige Eigenschaften sind: NotifyFilter Typ der zu überwachenden Änderung (in NotifyFilters-Enumeration enthalten, z.b. Attributes, CreationTime, DirectoryName, FileName, LastAccess, Size,...) Filter Filterzeichenfolge für die zu überwachenden Dateien EnableRaisingEvents Aktivieren der Komponente (True/False) Wichtige Ereignisse sind: Changed Datei oder Verzeichnis wurde geändert Created Datei oder Verzeichnis wurde erzeugt Deleted Datei oder Verzeichnis wurde gelöscht Renamed Datei oder Verzeichnis wurde umbenannt Oberfläche Ein Formular mit einer ListBox und einem Button soll genügen.