20.6 Datenübergabe zwischen den Seiten
Daten von einer Seite an eine andere zu übergeben stellt grundsätzlich kein Problem dar. Wir benötigen dazu nur einen parametrisierten Konstruktor. Allerdings müssen wir dann auch Programmcode schreiben, da der Aufruf eines parametrisierten Konstruktors aus XAML-Code heraus nicht möglich ist. Zur Vorbereitung muss nur der Konstruktor der betreffenden Seite überladen werden, z. B.:
public partial class Page2 : Page {
public int Value { get; set; }
public Page2() {
InitializeComponent();
}
public Page2(int param) : this() {
Value = value;
}
}
Listing 20.18 Parametrisierter Konstruktor einer »Page«
Sie dürfen dabei nicht vergessen, den Aufruf des parametrisierten Konstruktors an den parameterlosen weiterzuleiten, in dem die Methode InitializeComponent dafür sorgt, die Seite mit den gewünschten Steuerelementen auszustatten. Natürlich kann InitializeComponent auch direkt im parametrisierten Konstruktor angegeben werden. Vergessen Sie jedoch den Aufruf der Methode, zeigt Ihre Seite keine Steuerelemente an und bleibt leer.
Die Übergabe von Daten beim Aufruf der neuen Seite bedarf nun keiner besonderen Erklärung mehr. Der Code könnte zum Beispiel lauten:
NavigationService.Navigate(new Page2(20));
20.6.1 Datenübergabe mit der Methode »Navigate«
Eine andere Alternative bietet die Methode Navigate. Wir haben diese Methode bisher immer nur in ihrer einfachsten, parameterlosen Form benutzt, aber die Überladungen gestatten auch die Übergabe eines Arguments vom Typ Object. Der aufgerufenen Seite wird der Übergabewert in der Eigenschaft ExtraData des EventArgs-Parameters des Ereignisses LoadCompleted zur Verfügung gestellt.
Was sich im ersten Moment noch sehr einfach anhört, wird sich schnell als Hürde erweisen. Das Problem dabei ist die Registrierung des Ereignishandlers für das Ereignis LoadCompleted des NavigationService-Objekts. Stellen wir uns dazu vor, wir würden beabsichtigen, mit der parametrisierten Navigate-Methode von Page1 zu Page2 zu navigieren. Dazu muss der Ereignishandler für LoadCompleted des NavigationService-Objekts des Hosts in der Page2 registriert werden. Erst dann kann Page2 von den Informationen des EventArgs-Objekts profitieren. Allerdings stellt sich die Frage, wo die Registrierung des Ereignishandlers programmiert werden soll. Prinzipiell würden sich zwei Ereignisse der Seite anbieten: Initialized und Loaded. Jetzt kommt der Haken: Im Initialized-Event hat die Eigenschaft NavigationService der Seite noch den Wert null. Wird das Ereignis Loaded der Seite ausgelöst, hat das NavigationService-Objekt seinerseits bereits das Ereignis LoadCompleted ausgelöst. Mit anderen Worten: Das Ereignis Initialized kommt zu früh, Loaded zu spät.
Die Lösung dieses Dilemmas ist in einer zusätzlichen Methode zu finden, die von der aufgerufenen Seite bereitgestellt werden muss. Im folgenden Beispielprogramm, das die beiden Seiten Page1 und Page2 enthält, wird der Ablauf verdeutlicht. In Page1 befindet sich ein Button, von dem aus zur Page2 navigiert wird. Dabei wird der Inhalt der in Page1 befindlichen TextBox an die zweite Seite weitergeleitet (siehe auch Abbildung 20.4). Sehen wir uns aber zuerst das komplette Listing an.
// Beispiel: ..\Kapitel 20\NavigationSample
<NavigationWindow ...
Title="MainWindow" Height="200" Width="300"
Source="Page1.xaml">
</NavigationWindow>
<!-- Page1 -->
<Page ...
WindowTitle="Seite 1"
Title="Page1" WindowHeight="200">
<StackPanel>
<TextBox Name="TextBox1" ...></TextBox>
<Button Name="Button1" Click="Button1_Click" ...>
Zur Seite 2 navigieren
</Button>
</StackPanel>
</Page>
<!—Page2 -->
<Page ...
WindowTitle="Seite 2"
Title="Page2" WindowHeight="150">
<StackPanel>
<TextBox Name="TextBox1" ...></TextBox>
</StackPanel>
</Page>
// Code in Page1
public partial class Page1 : Page {
private void Button1_Click(object sender, RoutedEventArgs e) {
Page2 page = new Page2();
NavigationService nav = NavigationService.GetNavigationService(this);
page.SetLoadCompletedHandler(nav);
nav.Navigate(page,TextBox1.Text);
}
}
// Code in Page2
public partial class Page2 : Page {
public void SetLoadCompletedHandler(NavigationService nav) {
nav.LoadCompleted += new LoadCompletedEventHandler(nav_LoadCompleted);
}
void nav_LoadCompleted(object sender, NavigationEventArgs e) {
if (e.ExtraData != null && (e.ExtraData is String))
TextBox1.Text = (string)e.ExtraData;
this.NavigationService.LoadCompleted -= nav_LoadCompleted;
}
}
Listing 20.19 Das Beispielprogramm »NavigationSample«
Abbildung 20.4 Ausgabe des Beispielprogramms »NavigationSample«
Betrachten wir zuerst den Code in Page2. Die Seite stellt mit SetLoadCompletedHandler eine öffentliche Methode zur Verfügung, in der das Ereignis LoadCompleted registriert wird. Im Ereignishandler erfolgt die Auswertung der übermittelten Daten, die von der Eigenschaft ExtraData des NavigationEventArgs-Objekts bereitgestellt werden. Nach der notwendigen Überprüfung, ob die Daten von null abweichen und ob es sich um Daten vom Typ String handelt, wird der Übergabewert nach vorhergehender Typkonvertierung in die TextBox der Page2 eingetragen. Danach sollte die Registrierung des Ereignishandlers in jedem Fall wieder aufgehoben werden.
In Page1 wird nach der Instanziierung der Klasse Page2 die Methode SetLoadCompletedHandler aufgerufen und das NavigationService-Objekt als Argument übergeben. Damit sind alle vorbereitenden Maßnahmen getroffen, und die Navigate-Methode kann unter Übergabe des Inhalts der TextBox in Page1 aufgerufen werden.
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.