Silverlight Tutorial: Interaktion via Code-Behind

Willkommen zum dritten Silverlight Tutorial!

Diesmal werden wir lernen, wie man XAML- und C#-Code kombiniert, um etwas Interaktivität in unsere Webseite zu bringen.

Das Code-Behind

Im letzten Tutorial haben wir gelernt, wie man eine einfache Benutzeroberfläche in XAML erstellt. Leider war die noch sehr statisch und konnte nicht auf Benutzereingaben reagieren.

Während XAML sehr gut dafür geeignet ist, eine Oberfläche zu definieren, ist C#-Code das Mittel der Wahl, wenn es um die gesamte Applikations-Logik und das Reagieren auf Benutzereingaben geht.

Erstellt wie im letzten Tutorial beschrieben ein neues Silverlight Projekt.

Klickt jetzt im Solution-Explorer auf die Datei MainPage.xaml.cs. Ihr seht nun folgenden C#-Code:

public partial class MainPage : UserControl
{
        public MainPage()
        {
            InitializeComponent();
        }
}

Im Solution-Explorer ist erkennbar, dass die .cs Datei und die .xaml Datei durch einen Strich verbunden sind. Während in vielen Sprachen eine Klasse nur in genau einer Datei definiert werden kann, ist es in C# mit dem partial Schlüsselwort möglich, die Definition einer Klasse auf mehrere Dateien aufzuteilen.

In Silverlight wird dies verwendet, um eine Klassendefinition in XAML-Code (für die Benutzeroberfläche) und dem sogenannten Code-Behind (beispielsweise für das Behandeln von Benutzereingaben) aufzuteilen.

Wir werden diesmal zwei Möglichkeiten kennen lernen, wie XAML- und C#-Code miteinander kommunizieren können.

XAML-Objekte im Code-Behind ansprechen

Erzeugt wie folgt eine einfache Border in der MainPage.xaml:

<Grid x:Name="LayoutRoot">
        <Border x:Name="myBorder"
                Width="256" Height="256"
                Background="Black" />
</Grid>

Wenn ihr das Programm nun mit F5 ausführt, seht ihr unsere schwarze Border im Zentrum der Seite. Wir wollen nun als Beispiel die Hintergrundfarbe (also die Background-Eigenschaft) der Border aus dem Code-Behind ändern.

Geht dazu zurück zur MainPage.xaml.cs und erweitert den Konstruktor der Klasse um folgende Zeile:

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            myBorder.Background = new SolidColorBrush(Colors.Orange);
        }
    }

Wenn ihr das Programm jetzt ausführt, ist die Border orange anstatt schwarz.

Im XAML-Code haben wir dem Border-Objekt mit x:Name einen Namen zugewiesen, über den wir das Objekt im Code-Behind der XAML-Datei ansprechen können. Zu beachten ist, dass x:Name keine Eigenschaft der Border-Klasse ist, sondern eher eine Meta-Information, die man nur in XAML festlegen kann. Zwar haben viele Klassen eine richtige Name-Eigenschaft, jedoch eben nicht alle, weswegen man der Konsistenz wegen immer x:Name verwenden sollte.

Wenn wir das Programm ausführen, wird zuerst der Konstruktor der Klasse MainPage aufgerufen. Dort steht standardmäßig nur der Aufruf der Methode InitializeComponent(), die nichts weiter macht, als unseren XAML-Code in C# Code umzuwandeln, der zur Laufzeit die in XAML definierten Objekte erzeugt (wir haben ja gelernt, dass XAML und C# größtenteils äquivalent und damit austauschbar ist).

Ihr könnt diesen generierten C#-Code sehen, indem ihr rechts auf die Methode klickt und dann “Gehe zu Definition” auswählt.

In der nächsten Zeile sprechen wir die in XAML definierte Border mit ihrem Namen an und weisen ihr eine andere Hintergrundfarbe zu.

Hier könnte man sich Fragen, warum wir ein SolidColorBrush-Objekt zuweisen, und nicht einfach soetwas wie Colors.Orange. Das hat den Grund, dass die Background Eigenschaft ein Objekt vom Typ Brush erwartet, Orange aber den Typ Color hat.

In Silverlight gibt es verschiedene von Brush abgeleitete Klassen, die von einfachen Farben (SolidColorBrush) über verschiedene Gradienten (z.B. LinearGradientBrush) bis hin zu Bildern (ImageBrush) oder sogar Videos (VideoBrush) reichen.

Das ermöglichst es, all das als “Hintergrundfarbe” von Elementen oder beispielsweise als Schriftfarbe von Texten zu verwenden, was ein viel flexibleres System ist, als nur einfache Farben (Color-Structs) zuweisen zu können.

Auf die Verwendung der verschiedenen Brushes werde ich in späteren Tutorials eingehen.

Im Code-Behind auf Events reagieren

Was uns jetzt noch fehlt, ist eine Möglichkeit, auf Benutzereingaben zu reagieren.

GUI-Elemente wie Buttons und auch unsere Border definieren in ihren Klassen Events, die unter bestimmten Bedingungen vom Objekt ausgelöst werden. So löst beispielsweise ein Button-Objekt das Click-Event aus, wenn der User auf den Button klickt.

Um im Code auf das Event zu reagieren, muss man einen Event-Handler bei dem Event registrieren. Das kann man sich ähnlich wie die Anmeldung für einen Newsletter vorstellen (was natürlich eine arg konstruierte Metapher ist 😉 ). Wenn der Anbieter einen neuen Newsletter herausgibt (ein Event auslöst), werden alle angemeldeten Benutzer (Event-Handler) und nur diese Benutzer informiert.

Bei uns wird ein Event-Handler eine einfache Methode im Code-Behind sein, die aufgerufen wird, sobald ein Objekt ein Event auslöst. Es gibt noch weitere Methoden wie anonyme Delegates, um auf Events zu reagieren, aber die sollen uns hier noch nicht beschäftigen.

Geht wieder zum XAML-Code und erweitert das Border-Tag wie folgt:

<Border x:Name="border"
                Width="256" Height="256"
                Background="Black"
                MouseLeftButtonDown="border_MouseLeftButtonDown"/>

Wenn ihr anfangt, im Border-Tag zu tippen, öffnet sich eine Liste mit allen Eigenschaften und Events des Objekts. Events sind mit einem Blitz gekennzeichnet. Sobald ihr das Event MouseLeftButtonDown per Doppelklick oder Druck auf die Return-Taste ausgewählt habt, sollte ein neues Kontext-Menü erscheinen, dass euch anbietet, einen neuen Event-Handler zu erstellen. Hier klickt ihr wieder doppelt auf “<Neuer Ereignishandler>”, worauf das Visual Studio automatisch eine Methode im Code-Behind generiert und ihren Namen im XAML einträgt.

Somit wurde für das Event MouseLeftButtonDown die Methode border_MouseLeftButtonDown als Event-Handler registriert und das Code-Behind sieht nun so aus:

 public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            border.Background = new SolidColorBrush(Colors.Orange);
        }

        private void border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

        }
    }

In diese Methode können wir nun Code schreiben, der ausgeführt werden soll, wenn jemand auf die Border klickt. Typischerweise haben solche Event-Handler Methoden zwei Parameter: Im ersten Parameter sender übergibt sich das Objekt, das das Event auslöst, selbst. Der zweite Parameter ist meist von einem für das Event spezifischen Typ, der weitere Informationen über das Event bereitstellt. Beim MouseDown-Event werden beispielsweise auch die Koordinaten übergeben, an denen der Klick stattfand.

Eine weitere Möglichkeit, einen Event-Handler zu registrieren, ist dies direkt im Code-Behind zu tun. Auch hier hilft uns das VisualStudio und generiert die entsprechende Methode automatisch. Schreibt folgendes in den Konstruktor der MainPage:

border.MouseLeftButtonUp += new MouseButtonEventHandler(border_MouseLeftButtonUp);

Nachdem ihr += getippt habt, könnt ihr zwei mal die Tab-Taste betätigen, um automatisch den Zuweisungscode und die Methode border_MouseLeftButtonUp generieren zu lassen.

Der komplette Code sieht nun so aus:

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            border.Background = new SolidColorBrush(Colors.Orange);
            border.MouseLeftButtonUp += new MouseButtonEventHandler(border_MouseLeftButtonUp);

        }

        void border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

        }
    }

Wir haben jetzt jeweils eine Methode die aufgerufen wird, wenn der Benutzer auf die Border klickt (border_MouseLeftButtonDown), und die Maustaste wieder löslässt (border_MouseLeftButtonUp).

Wir wollen jetzt, um die Events zu visualisieren, die Hintergrundfarbe der Border je nach Event verändern, und erweitern den Code folgendermaßen:

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            border.Background = new SolidColorBrush(Colors.Orange);
            border.MouseLeftButtonUp += new MouseButtonEventHandler(border_MouseLeftButtonUp);
        }

        void border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            border.Background = new SolidColorBrush(Colors.Green);
        }

        private void border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            border.Background = new SolidColorBrush(Colors.Red);
        }
    }

Wenn ihr das Programm jetzt ausführt, sollte die Border beim Gedrückthalten der linken Maustaste rot, und beim Loslassen grün werden.

Ihr könnt jetzt gerne mit anderen Events experimentieren, und auch mal andere Eigenschaften als die Hintergrundfarbe verändern, um ein Gefühl für das Event-System zu kriegen.

Im folgenden Beispielprojekt werden noch einmal verschiedene Events und deren Verarbeitung demonstriert. Das war’s dann soweit zu diesem Thema. Im nächsten Tutorial werden wir uns einen weiteren wichtigen Aspekt von Silverlight ansehen: DataBinding.

Beispielprojekt herunterladen

Kommentare

2 Nachrichten zu “Silverlight Tutorial: Interaktion via Code-Behind”

  1. nice nice on 11. August 2010 14:22

    nice

  2. Lottaria vom Sa on 24. Januar 2011 03:22

    Da fragt man sich beim Überfliegen von http://www.eality.de schon, ob man nicht irgendwie bescheuert ist. Herzlichen Dank für Ihre Berichte