Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 20 Fenster in der WPF
Pfeil 20.1 Hosts der WPF
Pfeil 20.2 Fenster vom Typ »Window«
Pfeil 20.2.1 Mehrere Fenster in einer Anwendung
Pfeil 20.3 Fenster vom Typ »NavigationWindow«
Pfeil 20.3.1 Das »Page«-Element
Pfeil 20.4 Hosts vom Typ »Frame«
Pfeil 20.5 Navigation zwischen den Seiten
Pfeil 20.5.1 Navigation mit »HyperLink«
Pfeil 20.5.2 Der Verlauf der Navigation – das Journal
Pfeil 20.5.3 Navigation mit »NavigationService«
Pfeil 20.5.4 Navigation im Internet
Pfeil 20.5.5 Navigieren mit dem Ereignis »RequestNavigate« des »HyperLink«-Elements
Pfeil 20.6 Datenübergabe zwischen den Seiten
Pfeil 20.6.1 Datenübergabe mit der Methode »Navigate«
Pfeil 20.7 Nachrichtenfenster mit »MessageBox«
Pfeil 20.7.1 Die Methode »MessageBox.Show«

Rheinwerk Computing - Zum Seitenanfang

20.5 Navigation zwischen den SeitenZur nächsten Überschrift

Ein NavigationWindow dient als Host für eine oder x-beliebig viele Pages. Um dem Benutzer die Navigation zwischen den Seiten der Anwendung zu ermöglichen, werden Ihnen mit

  • HyperLink und
  • NavigationService

zwei Möglichkeiten angeboten. Darüber hinaus sind auch die Zustandsdaten in der navigationsauslösenden Seite ein wichtiger Gesichtspunkt. Bleiben sie erhalten, wenn zu der ursprünglichen Seite zurücknavigiert wird, oder sind sie verloren? Wie können Daten an eine neu anzuzeigende Seite übergeben werden? Diesen Fragen wollen wir uns in den folgenden Abschnitten widmen.


Rheinwerk Computing - Zum Seitenanfang

20.5.1 Navigation mit »HyperLink«Zur nächsten ÜberschriftZur vorigen Überschrift

Verwenden Sie ein HyperLink-Element zur Navigation, müssen Sie sowohl die Zieladresse als auch einen Text angeben, auf den der Benutzer klicken soll.

<TextBlock>
<Hyperlink NavigateUri="Page2.xaml">Zur Seite 2</Hyperlink>
</TextBlock>

Listing 20.9 Hyperlink zur Navigation zu einer anderen Seite

Das HyperLink-Element muss entweder in einem TextBlock oder einem FlowDocument eingebettet sein. Das Ziel des Hyperlinks wird in der Eigenschaft NavigateUri angegeben. Dabei muss man beachten, dass die XAML-Datei angegeben wird und nicht der Klassenbezeichner. Anstatt einer Zeichenfolge lassen sich, wie in HTML-Seiten, auch Bilder verlinken.

<TextBlock>
<Hyperlink NavigateUri="Page2.xaml">
<Image Source="TraumFrau.jpg" />
</Hyperlink>
</TextBlock>

Listing 20.10 Ein Image zur Navigation über »HyperLink«

Befindet sich die verlinkte XAML-Datei im aktuellen Verzeichnis, genügt die einfache Dateiangabe wie gezeigt. In der Entwicklungsumgebung können Sie aber innerhalb eines Projekts auch eine Verzeichnisstruktur festlegen, beispielsweise um Ressourcen besser verwalten zu können. Angenommen, die Seite mit dem Namen Page1.xaml würde sich im Ordner Friends befinden, müssten Sie die Seite wie folgt adressieren:

NavigateUri="../Friends/Page1.xaml

Beachten Sie jedoch, dass es sich dabei nicht um ein Verzeichnis handelt, das nach dem Kompilieren im Ausgabeverzeichnis des Kompilats zu finden ist.


Rheinwerk Computing - Zum Seitenanfang

20.5.2 Der Verlauf der Navigation – das JournalZur nächsten ÜberschriftZur vorigen Überschrift

Die Navigation mit Seiten erinnert uns an die Navigation in einem Browser. Immer dann, wenn wir zu einer neuen Seite navigieren, wird die alte Seite in eine »Zurück«-Liste eingetragen. Klicken wir in der zweiten Seite auf die »Zurück«-Schaltfläche, wird die erste Seite aus einem Stack geholt und angezeigt, während die zweite Seite in eine »Vorwärts«-Liste eingetragen wird.

Die Vorgänge, die sich dabei in WPF-Navigationsfenstern bei der Navigation im Hintergrund abspielen, sind ziemlich komplex. Nehmen wir an, in der WPF-Anwendung wären die beiden Seiten Page1 und Page2 vorhanden. Unterstellen wir nun eine Navigation von Page1 nach Page2 und wieder zurück zu Page1. Der letzte Schritt, zurück zu Page1 zu navigieren, resultiert in einer neuen Instanz von Page1.

So weit ist das noch alles sofort verständlich. Nun bauen wir aber in Page1 neben dem Hyperlink auf Page2 eine TextBox ein.

<StackPanel>
<TextBlock Height="15" Margin="20, 20, 20, 0">
<Hyperlink NavigateUri="Page2.xaml">Seite2 anzeigen</Hyperlink>
</TextBlock>
<TextBox Height="25" Margin="20" Background="AntiqueWhite" />
</StackPanel>

Listing 20.11 Inhalt der »Page1«

Starten Sie nun die Anwendung, und tragen Sie einen beliebigen Text in die TextBox ein. Navigieren Sie anschließend zu Page2 und danach zurück zu Page1. Die TextBox hat ihren Inhalt behalten. Stimmt jetzt die Aussage etwa nicht, dass bei der Navigation ein neues Page-Objekt erstellt wird?

Doch, sie stimmt. Aber wie ich schon zuvor erwähnt habe, sind die Vorgänge, die sich dabei abspielen, sehr komplex. Zunächst einmal werden tatsächlich die Page-Objekte beim Verlassen während der Navigation zerstört. Das hat einen ziemlich einfachen Grund, denn eine Seite kann sehr viele speicherintensive Ressourcen beschreiben. Denken Sie dabei nur an Grafiken, Video- bzw. Audiomedien oder Animationen. In einer Anwendung mit sehr vielen Seiten, in denen die Page-Objekte nicht zerstört würden, hätte das eine extreme Beanspruchung der Systemressourcen zur Folge. Daher speichert die WPF nur die Zustände der Steuerelemente der Seite. Führt die Navigation wieder zurück zu der ursprünglichen Seite, werden die Zustände der Steuerelemente wiederhergestellt. Dieses Verfahren schont die Ressourcen, weil nicht der gesamte visuelle Baum der Objekte gespeichert werden muss.

Nun müssen wir noch ein weiteres Detail betrachten, denn es werden nicht alle Steuerelementzustände einer Seite gespeichert. Sie können das sehr leicht testen, wenn Sie den XAML-Code aus Listing 20.11 um eine Schaltfläche erweitern, in der die Hintergrundfarbe der Seite neu festgelegt wird (siehe Listing 20.12).

// im XAML-Code
<StackPanel>
<TextBlock Height="15" Margin="20, 20, 20, 0">
<Hyperlink NavigateUri="Page2.xaml">Seite2 anzeigen</Hyperlink>
</TextBlock>
<TextBox Height="25" Margin="20" Background="AntiqueWhite" />
<Button Content="Button1" Width="100" Click="Button1_Click"/>
</StackPanel>
// in der Code-Behind-Datei
private void Button1_Click(object sender, RoutedEventArgs e) {
Background = new SolidColorBrush(Colors.Yellow);
}

Listing 20.12 Inhalt von »Page1«, ergänzt um eine Schaltfläche

Sie finden dieses Beispiel auf der Buch-DVD unter \Kapitel 20\NavigationHistory.

Sie werden feststellen, dass beim Zurücknavigieren die eingestellte Hintergrundfarbe verlorengeht, der Inhalt der TextBox jedoch nicht. Das Beispiel beweist, dass nicht die Zustände aller Eigenschaften gespeichert werden, sondern nur ein bestimmter Teil. Tatsächlich verfährt die WPF in der Weise, dass der gesamte Elementbaum durchlaufen und nach allen abhängigen Eigenschaften gesucht wird. Abhängige Eigenschaften haben eine ganze Reihe von zusätzlichen Eigenschaften, den sogenannten Metadaten. Zu diesen gehört auch das Journal-Flag, mit dem eine abhängige Eigenschaft kennzeichnet, dass der Zustand bei einer Navigation protokolliert werden soll.

Abhängige Eigenschaften sind vollkommen anders implementiert als CLR-Eigenschaften. Daher werden Sie eben mit etwas Verwunderung zur Kenntnis genommen haben, dass abhängige Eigenschaften durch Metadaten charakterisiert werden und auch ein Journal-Flag haben. Seien Sie geduldig, wir werden in einem späteren Kapitel noch sehen, wie abhängige Eigenschaften implementiert werden.

Was also können Sie tun, wenn Sie entgegen dem Standardverhalten alle Daten bewahren wollen? Es gibt dazu mehrere Ansätze. Der sicherlich einfachste Weg führt über die Eigenschaft KeepAlive der Seite, die Sie auf true festlegen können. Der Standard ist false. Damit werden alle Daten einer Seite gespeichert und nicht nur die mit dem Journal-Flag.

Die KeepAlive-Option sollten Sie mit Bedacht einsetzen und wirklich nur die Seiten so ausstatten, bei denen es wirklich notwendig ist. Wie angedeutet gibt es noch weitere Möglichkeiten, die aber im Rahmen dieses Buches nicht erörtert werden.


Rheinwerk Computing - Zum Seitenanfang

20.5.3 Navigation mit »NavigationService«Zur nächsten ÜberschriftZur vorigen Überschrift

Das HyperLink-Element eignet sich besonders zur Angabe im XAML-Code. Das ist sehr einfach umzusetzen, beispielsweise wenn Sie mit den Seitenaufrufen sequenziell Benutzereingaben anfordern, ähnlich wie bei einem Assistenten. In komplexeren Szenarien stellt sich das HyperLink-Element jedoch sehr schnell als unzureichend heraus. An dessen Stelle betritt die Klasse NavigationService die Bühne, die sowohl von einem NavigationWindow als auch von einem Frame zur Verfügung gestellt wird. Sie können sich die Referenz auf das NavigationService-Objekt besorgen, wenn Sie die statische Methode GetNavigationService aufrufen und die Referenz auf den Host als Argument übergeben, auf dessen NavigationService Sie zurückgreifen wollen:

NavigationService nav = NavigationService.GetNavigationService(this);

Listing 20.13 Abrufen des »NavigationService«-Objekts eines Hosts

Eine andere Möglichkeit bietet das Page-Objekt mit seiner Eigenschaft NavigationService. Diese liefert die Referenz auf den NavigationService des eigenen Hosts.

Die wohl wichtigste Methode des NavigationService-Objekts ist Navigate, der Sie die Seite als URI übergeben, zu der navigiert werden soll.

NavigationService nav = NavigationService.GetNavigationService(this);
Uri uri = new Uri("Page2.xaml", UriKind.RelativeOrAbsolute);
nav.Navigate(uri);

Listing 20.14 Übergabe eines »Uri«-Objekts an die Methode »Navigate«

Erwähnenswert im Zusammenhang mit Navigate ist, dass die Methode asynchron aufgerufen wird. Dieses Verhalten ist natürlich sinnvoll, da eine Seite durchaus auch Inhalte haben kann, deren Ladevorgang verhältnismäßig lange dauert. Hier seien noch einmal Mediendateien exemplarisch genannt.

Eine weitere Möglichkeit bietet sich, indem Sie ein Objekt der Page neu erzeugen, zu der navigiert werden soll, und dieses als Argument an Navigate übergeben:

NavigationService nav = NavigationService.GetNavigationService(this);
nav.Navigate(new Page2());

Listing 20.15 Übergabe eines »Page«-Objekts an die Methode »Navigate«

Sie dürfen die beiden in Listing 20.14 und Listing 20.15 nicht beliebig verwenden, weil es einen großen Unterschied gibt: Während bei der Übergabe des URI (siehe Listing 20.14) nur die entsprechenden Journal-befähigten Eigenschaften protokolliert werden, ist es beim Erzeugen eines neuen Page-Objekts über den Konstruktor (wie in Listing 20.15 gezeigt) das gesamte Objekt.

Diesem Nachteil der Objekterstellung über den Konstruktor steht aber andererseits der Vorteil gegenüber, dass Sie einen parametrisierten Konstruktor aufrufen können und damit der neu anzuzeigenden Seite Daten übergeben können.

Wollen Sie eine über die standardmäßigen Navigationsschaltflächen des Hosts hinausgehende Navigation in einer Seite realisieren (beispielsweise mit separaten Schaltflächen), können Sie die Methoden GoForward oder GoBack des NavigationService-Objekts benutzen. Beide Methoden lösen eine Ausnahme vom Typ InvalidOperationException aus, wenn die Navigation fehlschlägt. Um das zu vermeiden, sollte daher zuerst geprüft werden, ob eine Navigation zurück oder nach vorne überhaupt möglich ist. Auch dazu hilft Ihnen das NavigationService-Objekt weiter, diesmal mit seinen beiden Eigenschaften CanGoBack und CanGoForward. Beide liefern true als Ergebnis, wenn ein Navigationsverlauf nach vorne oder zurück möglich ist.

Wie bereits angedeutet, werden die Inhalte der aufgerufenen Seite mit der Methode Navigate asynchron abgerufen. So wundert es nicht, dass das NavigationService-Objekt mit StopLoading eine Methode bereitstellt, um die Navigation abzubrechen oder mit der Methode Refresh eine Seite neu zu laden.

Ereignisse des »NavigationService«-Objekts

Das Navigieren zu einer anderen Seite mit dem NavigationService-Objekt ist ein relativ komplexer Vorgang. Dabei werden mehrere Schritte der Reihe nach ausgeführt:

  • Die aufgerufene Seite muss zuerst lokalisiert werden.
  • Die Seiteninformationen müssen abgerufen werden.
  • Alle Ressourcen, die in der zu ladenden Seite enthalten sind, müssen geladen werden.
  • Erst nach den genannten drei Schritten ist die Seite so weit vorbereitet, dass sie erstellt werden kann, was zu der Auslösung der Ereignisse Initialized und Loaded der Seite führt. Das gilt natürlich nicht, wenn die Informationen aus dem Journal entnommen werden.
  • Zum Schluss wird die Seite dargestellt (gerendert).

Während des beschriebenen Ablaufs werden eine Reihe von Ereignissen durch das NavigationService-Objekt ausgelöst. In Tabelle 20.3 sind die wichtigsten Ereignisse aufgeführt.

Tabelle 20.3 Die Ereignisse eines »NavigationService«-Objekts

Ereignis Beschreibung

Navigating

Dieses Ereignis wird kurz vor dem Seitenwechsel ausgelöst. In diesem Ereignis kann der Seitenwechsel im letzten Moment noch abgebrochen werden, indem die Eigenschaft Cancel des EventArgs-Parameters auf true gesetzt wird.

Navigated

Wird dieses Ereignis ausgelöst, hat die Navigation bereits begonnen.

NavigationProgress

Dieses Ereignis tritt während des Ladevorgangs der Seite permanent auf. Im Ereignishandler lässt sich das EventArgs-Objekt auswerten. So können Sie die Eigenschaft MaxBytes auswerten, um zu erfahren, wie viele Daten die Seite insgesamt erfordert, während ReadBytes angibt, wie viele Daten bereits übertragen worden sind. Dieses Ereignis wird übrigens immer dann ausgelöst, wenn 1 KByte Daten geladen worden sind. Es eignet sich daher gut, um den Ladefortschritt anzuzeigen.

LoadCompleted

Dieses Ereignis wird ausgelöst, wenn der Inhalt der Seite, zu der navigiert worden ist, geladen wurde und die Seite mit dem Rendering begonnen hat.

NavigationFailed

Das Ereignis wird ausgelöst, wenn während des Ladevorgangs ein Fehler auftritt. Das kann beispielsweise der Fall sein, wenn die angegebene Seite nicht gefunden wird.

NavigationStopped

Dieses Ereignis wird infolge des Methodenaufrufs StopLoading ausgelöst.

Die aufgeführten Ereignisse werden auch von den Klassen Application, NavigationWindow und Frame ausgelöst. Somit ist es möglich, in Anwendungen, in denen mehrere Navigations-Hosts enthalten sind, die Navigation für jeden Host separat zu behandeln oder, über das Application-Objekt, eine gemeinsame Behandlung zu implementieren. Das Page-Objekt selbst löst im Zusammenhang mit der Navigation keine Ereignisse aus.


Rheinwerk Computing - Zum Seitenanfang

20.5.4 Navigation im InternetZur nächsten ÜberschriftZur vorigen Überschrift

Die Navigation ist nicht zwangsläufig auf die Seiten der aktuellen Anwendung beschränkt. Sie können der Eigenschaft Source des NavigationWindow auch eine Webadresse übergeben. Gleiches gilt auch für die Methode Navigate. Allerdings müssen Sie dann auch der Methode mitteilen, dass es sich um eine Absolutadresse handelt, beispielsweise mit:

nav.Navigate(new Uri("http://dotnet-training.de", UriKind.Absolute));

Sollten Sie nun der Meinung sein, Sie hätten es hierbei mit einer abgespeckten Variante eines WebBrowser-Steuerelements zu tun, liegen Sie falsch. Das Navigationsverhalten des NavigationWindow protokolliert unverständlicherweise nicht die besuchten Seiten im Internet. Drücken Sie die Zurück-Taste im Fenster, landen Sie wieder bei der Page, von der aus Sie sich die erste Webseite haben anzeigen lassen.


Rheinwerk Computing - Zum Seitenanfang

20.5.5 Navigieren mit dem Ereignis »RequestNavigate« des »HyperLink«-ElementsZur vorigen Überschrift

Eine weitere Variante zur Navigation bietet das Ereignis RequestNavigate des HyperLink-Objekts. Sehen wir uns das am besten an einem Beispiel an. Beginnen wir mit dem XAML-Code, in dem an das Ereignis RequestNavigate ein Ereignishandler gebunden wird.

<TextBlock>
<Hyperlink NavigateUri="Page2.xaml"
RequestNavigate="Hyperlink_RequestNavigate">
Zur Seite 2
</Hyperlink>
</TextBlock>

Listing 20.16 Ereignishandler im XAML-Code registrieren

In der Code-Behind-Datei der Seite wird ebenfalls die Methode Navigate von NavigationService aufgerufen. Als Argument wird die Eigenschaft Uri des EventArgs-Objekts weitergeleitet. Durch das Setzen von true der Eigenschaft Handled teilen wir dem Objekt mit, die Aktion selbst übernommen zu haben. Alle weiteren Operationen des Hyperlinks werden damit unterbunden.

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e){
NavigationService.Navigate(e.Uri);
e.Handled = true;
}

Listing 20.17 Der Ereignishandler des Events »RequestNavigate«

Mit dem Ereignishandler gewinnen wir ein hohes Maß an Flexibilität, die uns gestattet, parallel zur Navigation weitere Operationen auszuführen.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern