Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
WPF Events
Ereignisse und Ereignisbehandlung
Dr. Beatrice Amrhein
Überblick
� Einführung
� Die wichtigsten Ereignisse
� Der C# Code Behind
� Die Verbindung von WPF und C# Code
� Einige Beispiele
2Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Einführung
3Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Einführung
� Ein Ereignis tritt immer dann auf, wenn sich der Zustand der des GUI oder der Anwendung ändert.
� Ein Button wird angeklickt.
� Der Text einer TextBox wird verändert
� Die Grösse des Fensters wird verändert
� Die Maus wird bewegt
� . . .
� Der angemeldete Ereignis-Behandler (EventListener) reagiert auf das entsprechende Ereignis.
4Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Button,
TextBox,
Window, ….
Die wichtigsten Ereignisse
5Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Ereignis-Quelle Registriertes Ereignis
Button Click
Text-Komponente GotFocus / LostFocus / TextChanged
• Das Anklicken eines Buttons bewirkt ein Click-Event.
• Eine fokussierbare Komponente (Button, Text-Komponente, Fenster, …) wird zum Beispiel durch Anklicken mit der Maus aktiviert (GotFocus).
• Durch Anklicken einer anderen Komponente oder durch Drücken der Tabulator-Taste wird der Fokus abgegeben, bzw. an eine andere Komponente weitergegeben (LostFocus).
• Der Inhalt einer Textkomponente ändert sich (TextChanged).
Die wichtigsten Ereignisse
6Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Ereignis-Quelle Registriertes Ereignis
Window Activated / Deactivated Event / Closing / Closed /
Alle Mouse-Events (MouseEnter / MouseLeave / MouseMove, …)Key-Events (KeyUp / KeyDown)Focus-Events (GotFocus / LostFocus)
• Ein Fenster wird durch das Öffnen aktiviert, durch das Schliessen (verkleinert zum Icon) deaktiviert (Activated-/Deactivated).
• Bevor ein Fenster geschlossen ist (Closed-Event) kann (zum Beispiel für das Speichern des atuellen Zustands) ein Closing Event aufgerufen werden.
• Auf allen Steuerelementen werden Maus-Ereignisse ausgelöst (hineinfahren, verlassen, …)
• Das Drücken und Loslassen der Tasten auf der Tastatur bewirkt jeweils ein KeyUp, bzw. ein KeyDown Event.
Ereignis-Bindung via Eigenschaften Editor
7Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Click-Ereignis an einen Button verknüpfen
MainWindow.xaml
<Window x:Class="ev1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="340" FontSize="20">
<WrapPanel Margin="20" Width="300">
<Button Content="Gelb" Name="B1" Margin="20" Width="100"/>
<Button Content="Grün" Name="B2" Margin="20" Width="100"/>
<Label Name="label1" Margin="20" Width="260"></Label>
</WrapPanel>
</Window>
8Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Den Fokus auf den Button «Gelb» setzen
Click-Ereignis an einen Button verknüpfen
Im Eigenschaften-Fenster (Properties) auf die Ereignishandler wechseln
9Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Beim Click-Ereignis den Namen des Ereignis-Behandlers (z.B. B1_Click) eintippen und mit «Enter» abschliessen.Dadurch wird das entsprechende Event (Ereignis) an dem Button angemeldet (registriert).
Click-Ereignis: MainWindow.xaml.cs
using System.Windows;
namespace ev1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void B1_Click(object sender, RoutedEventArgs e)
{
}
}
}
10Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Visual Studio wechselt den Fokus automatisch auf den Editor in MainWindow.xaml.cs, wo der leere Ereignis-Behandler erzeugt wurde.
Ereignis-Behandler dürfen zwar beliebige Namen haben, sie müssen aber immer genau die vorgegebene Signatur haben.
Click-Ereignis an einen Button verknüpfen
using System.Windows;
namespace ev1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void B1_Click(object sender, RoutedEventArgs e)
{
label1.Content = "Hallo";
label1.Background = Brushes.Yellow;
}
}
}
11Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Den Inhalt (die Logik) der Ereignis-Behandlung muss von Hand eingegeben (programmiert) werden.
Click-Ereignis an einen Button verknüpfen
Für den zweiten Button (B2) kann analog vorgegangen werden.
12Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Für das Click-Ereignis des Button B2 den Namen des Ereignis-Behandlers (z.B. B2_Click) eintippen und mit «Enter» abschliessen.
Click-Ereignisse: MainWindow.xaml.cs
namespace ev1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void B1_Click(object sender, RoutedEventArgs e)
{
label1.Content = "Hallo";
label1.Background = Brushes.Yellow;
}
private void B2_Click(object sender, RoutedEventArgs e)
{
}
}
}
13Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Auch für B2_Click wird eine leere Hülle erzeugt, welche dann «von Hand» ausprogrammiert werden muss
Click-Ereignisse: MainWindow.xaml.cs
namespace ev1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void B1_Click(object sender, RoutedEventArgs e)
{
label1.Content = "Hallo";
label1.Background = Brushes.Yellow;
}
private void B2_Click(object sender, RoutedEventArgs e)
{
label1.Content = "Tschüss";
label1.Background = Brushes.GreenYellow;
}
}
}
14Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Click-Ereignis: MainWindow.xaml
<Window x:Class="ev1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="340" FontSize="20">
<WrapPanel Margin="20" Width="300">
<Button Content="Gelb" Name="B1" Margin="20" Width="100" Click="B1_Click"/>
<Button Content="Grün" Name="B2" Margin="20" Width="100" Click="B2_Click"/>
<Label Name="label1" Margin="20" Width="260"></Label>
</WrapPanel>
</Window>
15Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Im XAML Code wurden automatisch die entsprechenden Ereignis-Behandler registriert.
Maus-Ereignis an ein Label verknüpfen
Auch an ein Label kann ein Ereignis (z.B. ein Maus-Ereignis) verknüpft werden.
MainWindow.xaml
<Window x:Class="ev1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="340" FontSize="20">
<WrapPanel Margin="20" Width="300">
<Button Content="Gelb" Name="B1" Margin="20" Width="100" Click="B1_Click"/>
<Button Content="Grün" Name="B2" Margin="20" Width="100" Click="B2_Click"/>
<Label Name="label1" Margin="20" Width="260"></Label>
</WrapPanel>
</Window>
16Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Den Fokus auf das leere Label «label1» setzen
Maus-Ereignis an ein Label verknüpfen
Aus der Liste der möglichen Ereignisse «MouseEnter» auswählen und z.B. LabelMausEnter als Name des Ereignis-Behandlers wählen und mit «Enter» abschliessen.
Dies erzeugt im File MainWindow.xaml.cs den folgenden Ereignis-Behandler
private void LabelMausEnter(object sender, MouseEventArgs e)
{
}
17Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Maus-Ereignis: MainWindow.xaml.cs
namespace ev1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void B1_Click(object sender, RoutedEventArgs e) { . . . }
private void B2_Click(object sender, RoutedEventArgs e) { . . . }
private void LabelMausEnter(object sender, MouseEventArgs e)
{
label1.Background = Brushes.White;
}
}
}
18Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Den Ereignis-Code im Ereignis-Behandler ergänzen
Maus-Ereignis: MainWindow.xaml
<Window x:Class="ev1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="340" FontSize="20">
<WrapPanel Margin="20" Width="300">
<Button Content="Gelb" Name="B1" Margin="20" Width="100" Click="B1_Click"/>
<Button Content="Grün" Name="B2" Margin="20" Width="100" Click="B2_Click"/>
<Label Name="label1" Margin="20" Width="260" MouseEnter="LabelMausEnter"/>
</WrapPanel>
</Window>
19Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Vom Eigenschaften-Editor erzeugte Verknüpfung.
Der Effekt: Sobald die Maus über das Label fährt, wird die Hintergrundfarbe wieder auf weiss gesetzt.
Ereignisse an Eigenschaften-Änderungen verknüpfen
20Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Daten-Änderungen überwachen
Ein Label soll jeweils den aktuellen Wert eines Zählers anzeigen. Jedesmal wenn der Wert des Zählers sich ändert, muss das Label den Wert neu lesen und darstellen.
21Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Der Button soll bei jedem Klick den Wert des Zählers um 1 erhöhen
Der Zähler soll eine überwachte Eigenschaft (Property) sein und bei jeder Änderung den neuen Wert dem Label wieder bekannt geben.
In einem vertikalen StackPanel Button und Label einfügen.
Im Button den Click-Event Ereignis-Behandler, im Label das Data-Binding definieren.
Daten-Änderungen überwachen: MainWindow.xaml.cs
<Window x:Class="ev4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="250" FontSize="20">
<StackPanel Orientation="Vertical" >
<Button Margin="15" Click="ButtonClick"> Erhöhe den Wert </Button>
<Label HorizontalAlignment="Center">
<Binding Path="Zaehler"/>
</Label>
</StackPanel>
</Window>
22Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Daten-Änderungen überwachen: MainWindow.xaml.cs
using System.Windows;
namespace ev4
{
public partial class MainWindow : Window
{
Daten daten;
public MainWindow()
{
InitializeComponent();
daten = new Daten();
DataContext = daten;
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
daten.Erhoehe();
}
}
}
23Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
ButtonClick Methode programmieren.
Daten Objekt erzeugen undals DataContext festlegen
Daten-Änderungen überwachen: Daten Klasse
using System.ComponentModel;
using System.Windows.Media;
namespace ev4
{
class Daten : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
24Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Damit die Klasse Daten überwachte Eigenschaften (Properties) haben kann, muss sie das Interface INotifyPropertyChangedimplementieren.
Das Interface bietet ein event vom Typ PropertyChangedEventHandler, welches PropertyChanged heisst. Dieses ist bereits in C# implementiert und kann hier benutzt werden.
Daten-Änderungen überwachen: Daten Klasse
Die Ereignis-Methode PropertyChanged bewirkt, dass jede Daten-Änderung der Property mit Namen propertyName an das GUI bekannt gegeben wird.
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
25Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Property Zaehler überwachen: Daten Klasse
private int zaehler = 0;
public int Zaehler
{
get { return zaehler; }
set {
zaehler = value;
PropertyChanged(this, new PropertyChangedEventArgs("Zaehler"));
}
}
26Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Durch den Aufruf von PropertyChanged in der set-Methode wird Zaehler eine überwachte Property. Jede Wert-Änderung von Zaehler wird sofort an das GUI bekannt gegeben.
Die vollständige Daten Klasse
class Daten : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int zaehler = 0;
public int Zaehler
{
get { return zaehler; }
set { zaehler = value;
PropertyChanged(this, new PropertyChangedEventArgs("Zaehler"));
}
}
public void Erhoehe()
{
Zaehler = Zaehler+1;
}
}
27Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Methode Erhoehe wird von der EreignisMethodeButtonClick aufgerufen und erhöht jeweils den Wert von Zaehler um 1.Dadurch wird die set-Methode von Zaehler aufgerufen, welche ein PropertyChanged event erzeugt, welches die Änderungs-Meldung an das GUI ausliefert.
public int Zaehler
{
get { return zaehler; }
set { zaehler = value;
PropertyChanged(this, new PropertyChangedEventArgs("Zaehler")); }
}
Der vollständige Ablauf
28Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Button
Click
MainWindow.xaml.cs
private void ButtonClick(object sender, RoutedEventArgs e)
{
daten.Erhoehe();
}
MainWindow.xaml
<Button Click="ButtonClick"> . . .
Daten.cs
public void Erhoehe()
{
Zaehler = Zaehler+1;
}
MainWindow.xaml
<Label>
<Binding Path="Zaehler"/>
</Label>
1
2
3
4
5
6
7
Mehrere Eigenschaften einer Klasse überwachen
29Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Weitere überwachte Eigenschaft: LabelFarbe
private Brush labelFarbe;
public Brush LabelFarbe
{
get { return labelFarbe; }
set { labelFarbe = value;
PropertyChanged(this, new PropertyChangedEventArgs("LabelFarbe"));
}
}
30Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Daten Klasse wird um eine weitere überwachte Eigenschaft (hier LabelFarbe) erweitert. Auch diese ruft bei jeder Änderung die Ereignis-Methode PropertyChanged auf.
Erweiterte Erhoehe Methode
public void Erhoehe()
{
Zaehler = Zaehler+1;
if(Zaehler > 5)
LabelFarbe = Brushes.Yellow;
if (Zaehler > 10)
LabelFarbe = Brushes.YellowGreen;
if (Zaehler > 15)
LabelFarbe = Brushes.Green;
}
31Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Wir ändern in der Erhöhe Methode (abhängig vom Wert von Zaehler) den Wert der überwachten Eigenschaft LabelFarbe.
Verbinden der Hintergrundfarbe des Labels
<Window x:Class="ev5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="250" FontSize="20">
<StackPanel Orientation="Vertical" >
<Button Margin="15" Click="ButtonClick"> Erhöhe den Wert </Button>
<Label HorizontalAlignment="Center" Background="{Binding LabelFarbe}">
<Binding Path="Zaehler"/>
</Label>
</StackPanel>
</Window>
32Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Hintergrundfarbe des Labels wird an die Eigenschaft LabelFarbe der Klasse Daten gebunden.
MainWindow.xaml
<Label Background="{Binding LabelFarbe}>
<Binding Path="Zaehler"/>
</Label>
set
{
labelFarbe = value;
PropertyChanged(this, new PropertyChangedEventArgs("LabelFarbe"));
}
Der Ereignis-Ablauf für Hintergrund Farbe des Labels
33Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Button
Click
MainWindow.xaml.cs
private void ButtonClick(object sender, RoutedEventArgs e)
{
daten.Erhoehe();
}
MainWindow.xaml
<Button Click="ButtonClick"> . . .
Daten.cs
public void Erhoehe()
{
. . .
LabelFarbe = Brushes.Green;
}
1
2
3
4
5
6
7
34Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Timer Events
� Stoppuhr
Stoppuhr: MainWindow.xaml
<Window x:Class="ev4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="300" FontSize="18">
<DockPanel>
<UniformGrid Rows="1" DockPanel.Dock="Bottom" Margin="20,5">
<Button Content="Start" Click="StartEvent"/>
<Button Content="Stop" Click="StopEvent"/>
<Button Content="Reset" Click="ResetEvent"/>
</UniformGrid>
<UniformGrid Rows="1" Margin="20,20,20,5">
<Label HorizontalAlignment="Center">Sekunden</Label>
<Label HorizontalAlignment="Center">
<Binding Path="Time"/>
</Label>
</UniformGrid>
</DockPanel>
</Window>
35Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Das Label wird an die Property Time gebunden.
Die drei Buttons erhalten je ein Click Event.
Stoppuhr: MainWindow.xaml.cs
using System.Windows;
namespace ev4
{
public partial class MainWindow : Window
{
Stoppuhr stoppuhr;
public MainWindow()
{
InitializeComponent();
stoppuhr = new Stoppuhr();
DataContext = stoppuhr;
}
36Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Stoppuhr erzeugen und als DataContext (Daten-Quelle) setzen.
private void StartEvent(object sender, RoutedEventArgs e)
{ . . . }
Stoppuhr: MainWindow.xaml.cs
private void StartEvent(object sender, RoutedEventArgs e)
{
stoppuhr.Start();
}
private void StopEvent(object sender, RoutedEventArgs e)
{
stoppuhr.Stop();
}
private void ResetEvent(object sender, RoutedEventArgs e)
{
stoppuhr.Reset();
}
}
}
37Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Ereignis-Methoden für die Buttons (Start, Stop und Reset)
<Button Content="Start" Click="StartEvent"/> public void Start()
{ . . . }
StoppUhr.cs
MainWindow.xaml
MainWindow.xaml.cs
1 2
3
4
Die Klasse Stoppuhr
using System;
using System.ComponentModel;
using System.Windows.Threading;
namespace ev4
{
public class Stoppuhr : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private DispatcherTimer dispatcherTimer;
private int intervall = 250;
38Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Klasse Stoppuhr soll überwachte Eigenschaften (Properties) haben. Sie muss darum INotifyPropertyChangedimplementieren.
Für das Messen der aktuellen Zeit benötigen wir einen Timer vom Typ DispacherTimer (C# Klasse).
In der Variablen intervall wird gespeichert, wie viele Millisekunden zwischen zwei Timer-Events verstreichen sollen.
Die Klasse Stoppuhr
public Stoppuhr()
{
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, intervall);
dispatcherTimer.Tick += new EventHandler(TimerEvent);
}
private double anzahlTicks;
public double AnzahlTicks
{
get { return anzahlTicks; }
set { anzahlTicks = value; }
}
39Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Der Konstruktor erzeugt ein Dispatcher-Timer Objekt. Das Timer-Intervall wird auf die vordefinierte Anzahl Millisekunden gesetzt.
Das Ereignis (Delegate) der Klasse DispacherTimer heisst Tick. An dieses muss unser EventHandler angemeldet werden.
AnzahlTicks speichert die Anzahl Timer-Events, welche seit dem Starten der Stoppuhr eingetroffen sind.
Die Klasse Stoppuhr
private String time;
public String Time
{
get { return time; }
set { time = value; AenderungMelden("Time"); }
}
private void AenderungMelden(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
40Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Time ist eine überwachte Property. Sie speichert, wieviel Zeit seit dem Starten der Stoppuhr verstrichen ist.
Die Methode AenderungMeldenmeldet die Datenänderung, mit Hilfe eines PropertyChangeEvents.
Die Klasse Stoppuhr: Das TimerEvent
private void TimerEvent(object sender, EventArgs e)
{
AnzahlTicks++;
int min = (int)AnzahlTicks * intervall / 60000;
double sec = AnzahlTicks * intervall / 1000 - min * 60;
Time = String.Format(" {0}m {1:F2}s", min, sec);
}
41Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Methode TimerEvent erhöht die AnzahlTicks und berechnet daraus die verstrichene Zeit in Minuten und Sekunden. Time ist dann der formatierte Ausgabe-String.
Die Klasse Stoppuhr: Start/Stop/Reset
public void Start()
{
dispatcherTimer.Start();
}
public void Stop()
{
dispatcherTimer.Stop();
}
public void Reset()
{
AnzahlTicks = 0; Time = "0s 0.00m";
}
42Nach dem Handbuch der .NET 4.0-Programmierung, Rolf Wenger, 2012
Die Methoden Start und Stopsind für das Steuern des Timerszuständig.
Start()
Stoppuhr
Start()
DispacherTimer
TimerEvent()
Stoppuhr
Nach 250
msec AnzahlTicks++;
Time = . . . AenderungMelden()
PropertyChanged
Die Methode Reset setzt die Zeit (Anzahl Ticks) auf 0 zurück.