Programowanie obiektowe i zdarzeniowewykład 1 – Wprowadzenie do programowania zdarzeniowego
Wymagania wstępne: Znajomość podstaw programowania.Efekty kształcenia: Umiejętność tworzenia prostych aplikacji okienkowych w środowisku Microsoft Visual Studio, wykorzystujących techniki programowania obiektowego w języku C#.Treści kształcenia:
1. Wprowadzenie do WPF. Tworzenie interfejsu użytkownika.2. Pojecie klasy i obiektu. Składniki klas – pola i metody. Konstruktory.3. Okna dialogowe i kontrolki zawartości. Wiązanie danych.4. Kompozycja. Kolekcje. Kontrolki list.5. Dziedziczenie.6. Polimorfizm.7. Wyjątki. Style.8. Grafika i animacja w WPF.
Oprogramowanie: Microsoft Visual Studio 2008 lub nowsze (może być w wersji Express) wraz z dostępnym w nim systemem pomocy (MSDN).Dodatkowa literatura:
1. Adam Boduch, Wstęp do programowania w języku C#, Helion2. Krzysztof Rychlicki-Kicior, Tworzenie aplikacji graficznych w .NET 3.0, Helion3. Matthew MacDonald, Pro WPF in C# 2008: Windows Presentation Foundation with
.NET 3.5
1/34
Co to jest programowanie obiektowe? Co to jest programowanie zdarzeniowe?
Typowa aplikacja konsolowa (w C):
#include "stdio.h"
int main(){
int a, b, c;printf("Podaj pierwszą liczbę: ");scanf("%d", &a);printf("Podaj drugą liczbę: ");scanf("%d", &b);c = a + b;printf("Suma = %d", c);return 0;
}
2/34
Co to jest programowanie obiektowe? Co to jest programowanie zdarzeniowe?
Typowa aplikacja konsolowa (w C++):
#include "iostream"using namespace std;
int main(){
int a, b, c;cout << "Podaj pierwszą liczbę: ";cin >> a;cout << "Podaj drugą liczbę: ";cin >> b;c = a + b;cout << "Suma = " << c;return 0;
}
3/34
Co to jest programowanie obiektowe? Co to jest programowanie zdarzeniowe?
Typowa aplikacja konsolowa (w C#):
using System;
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int a, b, c; Console.Write("Podaj pierwszą liczbę: "); a = int.Parse(Console.ReadLine()); Console.Write("Podaj drugą liczbę: "); b = int.Parse(Console.ReadLine()); c = a + b; Console.Write("Suma = {0}", c); Console.ReadKey(); } }}
4/34
Jak powinna wyglądać aplikacja okienkowa?
Krok pierwszy – tworzenie interfejsu użytkownika (wizualne lub w kodzie).
5/34
Jak powinna wyglądać aplikacja okienkowa?
Krok drugi – obsługa zdarzeń.(chcemy, aby akcja użytkownika spowodowaławykonanie naszego kodu)
6/34
void Oblicz(...){ ... ... ...}
Jak powinna wyglądać aplikacja okienkowa?
Krok trzeci – interakcja z kontrolkami.(chcemy odczytać wprowadzone przezużytkownika dane, wykonać obliczeniai wyświetlić wynik)
7/34
void Oblicz(...){ ... ... ...}
Dlaczego programowanie obiektowe?
• Jest bliższe postrzeganiu świata przez człowieka, który najpierw dostrzega pewne rzeczy, pojęcia (obiekty), a nie wykonywane przez nie czynności (funkcje).
• W programowaniu obiektowym, program to zbiór obiektów posiadających określone cechy (właściwości). Mogą one wchodzić między sobą w interakcje lub łączyć się w bardziej złożone struktury.
• Obiekt to serwer usług – może wykonać pewną operację, jeśli zostanie poproszony. Taka usługa nazywa się metodą obiektu.
• W aplikacji okienkowej obiektami są np. elementy, z których składamy interfejs użytkownika – okno, pola tekstowe, przyciski, etc.
Język C# (C Sharp):• Prosty, nowoczesny, uniwersalny, język zorientowany obiektowo.• Zaprojektowany przez Microsoft, powiązany z platformą .NET.• Programy w nim napisane wymagają środowiska uruchomieniowego (takiego
jak .NET lub Mono).
8/34
WPF – Windows Presentation Foundation
• Interfejs programowania aplikacji okienkowych w systemie Windows.• Wykorzystuje DirectX do rysowania okien i zawartości.• Niezależność od rozdzielczości (oparcie się na „jednostkach
logicznych”=1/96 cala) – umożliwia łatwe skalowanie i dopasowanie do rozdzielczości ekranu.
• Ułożenie kontrolek: dynamiczne, oparte na zawartości (dopasowują się do swojej zawartości oraz dostępnego miejsca).
• Obiektowy model rysowania oparty na grafice wektorowej.• Wsparcie dla mediów i grafiki 3D.• Deklaratywne tworzenie animacji.• Style i szablony – pozwalają dopasowywać formatowanie i sposób renderowania
elementów interfejsu.• Deklaratywne*) tworzenie interfejsu użytkownika (XAML) – pozwala oddzielić
wygląd interfejsu od kodu.
*) Deklaratywne – czyli nie opisujemy kroków prowadzących do rozwiązania (algorytmu), a jedynie samo rozwiązanie. Nie mówmy jak ma być coś zrobione, ale co ma być zrobione.
9/34
XAML – Extensible Application Markup Language
• oparty na XMLu*) (deklaratywny) język do tworzenia interfejsu• definiuje ułożenie (oraz inne cechy) kontrolek w oknie• pozwala na podział pracy pomiędzy programistów i grafików (twórców interfejsu)• XAML nie jest obowiązkowy – to samo można zrobić w kodzie, ale wymaga to
większego nakładu pracy• można korzystać z narzędzi wizualnych do generowania plików XAML (np.
Microsoft Expression Blend)• warto znać XAMLa aby móc w pełni wykorzystywać możliwości WPFa
*) XML – uniwersalny język znaczników do strukturalnego reprezentowania danych
10/34
11/34
XML – wprowadzenie
prawidłowy plik XML
<!-- komentarz --><lista> <osoba> Kowalski </osoba> <osoba imię="Piotr" nazwisko="Nowak"> <telefon numer="0123456789"/> </osoba></lista>
12/34
znacznik zamykający
atrybuty
znacznik pusty
znacznik otwierający
XML – wprowadzenie
nieprawidłowy plik XML
<lista> <osoba>Nowak</Osoba> <osoba> <adres> </osoba> </adres></lista><osoba> Kowalski</osoba>
13/34
XAML
• każdy znacznik odpowiada określonemu elementowi interfejsu• możliwe jest zagnieżdżanie – używane do określenia zawierania np. jednych
elementów w innych• ustawianie właściwości przez atrybuty
<Window ... Title="Okienko" Height="200" Width="300" FontSize="14"> <Grid> <Button Margin="30"> Nie dotykać </Button> </Grid></Window>
14/34
Element <Window> – okno aplikacji
<Window ... Title="Okienko" Height="200" Width="300" FontSize="14"> <Grid> <Button Margin="30"> Nie dotykać </Button> </Grid></Window>
Przykładowe atrybuty okna:• Title – tekst na pasku tytułowym• Height – wysokość• Width – szerokość• FontSize – rozmiar czcionki używanej przez wszystkie kontrolki w oknie
15/34
Układy zawartości
<Window ... Title="Okienko" Height="200" Width="300" FontSize="14"> <Grid> <Button Margin="30"> Nie dotykać </Button> </Grid></Window>
Okno może zawierać tylko jeden element. Aby umieścić ich więcej musimy wykorzystać specjalny element, który posłuży za kontener dla innych kontrolek.
• jest on odpowiedzialny za ułożenie kontrolek w oknie• dba o dopasowanie kontrolek do zawartości• oraz do dostępnego miejsca
• elementy nie powinny mieć ustalonego rozmiaru• nie powinny mieć ustalonego położenia (współrzędnych)• o te aspekty będzie dbał kontener• różne rodzaje (typy) kontenerów będą kierować się różną logiką rozmieszczania
elementów
16/34
<StackPanel>
<Window ...> <StackPanel> <Button>jeden</Button> <Button>dwa</Button> <Button>trzy</Button> <Button>cztery</Button> </StackPanel> </Window>
17/34
<StackPanel>
<Window ...> <StackPanel Orientation="Horizontal"> <Button>jeden</Button> <Button>dwa</Button> <Button>trzy</Button> <Button>cztery</Button> </StackPanel>
</Window>
18/34
Przy pomocy atrybutów możemy sterować ułożeniem kontrolek:
<Window ...> <StackPanel Orientation="Horizontal"> <Button VerticalAlignment="Top">jeden</Button> <Button VerticalAlignment="Center">dwa</Button> <Button VerticalAlignment="Bottom">trzy</Button> <Button VerticalAlignment="Stretch">cztery</Button> </StackPanel> </Window>
• VerticalAlignment• HorizontalAlignment
19/34
Margin – dodaje odstęp od krawędzi kontenera i sąsiednich elementów:
<Window ...> <StackPanel> <Button HorizontalAlignment="Left" Margin="5"> jeden</Button> <Button HorizontalAlignment="Right" Margin="5"> dwa</Button> <Button Margin="5">trzy</Button> <Button Margin="15, 5">cztery</Button> <Button Margin="30, 5, 15, 0">pięć</Button> </StackPanel> </Window>
• marginesy sąsiadującychkontrolek sumują się!
20/34
Podobnie sterujemy ułożeniem zawartości wewnątrz kontrolki:
<Window ...> <StackPanel> <Button HorizontalContentAlignment="Left"> jeden</Button> <Button HorizontalContentAlignment="Right"> dwa</Button> <Button HorizontalContentAlignment="Center"> trzy</Button> <Button>cztery</Button> </StackPanel> </Window>
• VerticalContentAlignment• HorizontalContentAlignment
21/34
Podobnie sterujemy ułożeniem zawartości wewnątrz kontrolki:
<Window ...> <StackPanel> <Button HorizontalAlignment="Center"> jeden</Button> <Button HorizontalAlignment="Center" Padding="5"> dwa</Button> <Button HorizontalAlignment="Center" Padding="15, 5"> trzy</Button> <Button HorizontalAlignment="Center" Padding="30, 0, 15, 5">cztery</Button> </StackPanel> </Window>
• Padding steruje odstępemod zawartości kontrolki
22/34
<WrapPanel>
<Window ...> <WrapPanel> <Button Margin="5">jeden</Button> <Button Margin="5">dwa</Button> <Button Margin="5">trzy</Button> <Button Margin="5">cztery</Button> <Button Margin="5">pięć</Button> <Button Margin="5">sześć</Button> </WrapPanel></Window>
23/34
<DockPanel>
<Window ...> <DockPanel> <Button DockPanel.Dock="Top">jeden</Button> <Button DockPanel.Dock="Left">dwa</Button> <Button DockPanel.Dock="Right">trzy</Button> <Button DockPanel.Dock="Bottom">cztery</Button> <Button DockPanel.Dock="Top">pięć</Button> <Button DockPanel.Dock="Right">sześć</Button> <Button>siedem</Button> </DockPanel></Window>
• kolejność elementówma znaczenie!
24/34
„dołączonewłaściwości”
<Grid>
<Window ...> <Grid ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> ... ... ... </Grid></Window>
• elementy umieszczamyw polach siatki
• krok pierwszy –zdefiniowanie siatki
25/34
tylko dotestu
<Grid>
<Window ...> <Grid> <Grid.RowDefinitions>...</Grid.RowDefinitions> <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions> <Button>jeden</Button> <Button Grid.Row="1">dwa</Button> <Button Grid.Column="2">trzy</Button> <Button Grid.Row="1" Grid.Column="1">cztery</Button> </Grid></Window>
• krok drugi –rozmieszczenie elementów
26/34
<Grid>
<Window ...> <Grid> <Grid.RowDefinitions>...</Grid.RowDefinitions> <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions> <Button Grid.ColumnSpan="2">jeden</Button> <Button Grid.Row="1">dwa</Button> <Button Grid.Column="2" Grid.RowSpan="2">trzy</Button> <Button Grid.Row="1" Grid.Column="1">cztery</Button> </Grid></Window>
• element może rozciągać sięna więcej niż jedno pole siatki
27/34
<Grid>
<Window ...> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="70"/> </Grid.ColumnDefinitions> ... ... </Grid></Window>
• Width dla kolumn• Height dla wierszy
28/34
Kontenery można dowolnie zagnieżdżać:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <StackPanel> ... </StackPanel> <StackPanel Grid.Column="1" Orientation="Horizontal"> ... </StackPanel> <WrapPanel Grid.Column="2"> ... </WrapPanel></Grid>
29/34
A jak zaprojektujemy nasze okienko?
<Window ... Title="Obliczenia" Height="200" Width="300" FontSize="14"> ...</Window>
30/34
<Window ...> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> </Grid></Window>
• cztery wiersze, dwie kolumny• wysokość wierszy dopasowuje się
do zawartości• szerokość pierwszej kolumny
dopasowuje się do zawartości• szerokość kolumny z polem
tekstowym – rozciągnięta
31/34
<Window ...> <Grid> <Grid.RowDefinitions>...</Grid.RowDefinitions> <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>
<Label Margin="5">Pierwsza liczba:</Label> <Label Margin="5" Grid.Row="1">Druga liczba:</Label> <Label Margin="5" Grid.Row="2">Wynik:</Label> <TextBox Margin="5" Grid.Column="1"/> <TextBox Margin="5" Grid.Row="1" Grid.Column="1"/> <TextBox Margin="5" Grid.Row="2" Grid.Column="1" IsReadOnly="True"/> <Button Grid.Row="3" Grid.ColumnSpan="2" Margin="5" Padding="10,3" HorizontalAlignment="Right"> Oblicz</Button> </Grid></Window>
• Label – etykieta• TextBox – pole tekstowe
◦ IsReadOnly – tylko do odczytu• przycisk zajmuje cały wiersz
32/34
Jak dodać obsługę zdarzeń?
• również przy pomocy atrybutów:
<Button Click="Oblicz" ...>Oblicz</Button>
// zawartość pliku Window1.xaml.cs:namespace WpfApplication1{ public partial class Window1 : Window { public Window1() { InitializeComponent(); }
private void Oblicz(object sender, RoutedEventArgs e) {
} }}
33/34
Ta funkcja zostanie wywołana, gdy użytkownik naciśnie przycisk „Oblicz”
Jak odczytać dane z okna w kodzie programu?
• najpierw musimy nazwać elementy, do których chcemy mieć dostęp:
<TextBox Name="pierwsze" .../><TextBox Name="drugie" .../><TextBox Name="wynik" ... IsReadOnly="True"/>
• następnie w pliku *.cs:
private void Oblicz(object sender, RoutedEventArgs e){ int a = int.Parse(pierwsze.Text); int b = int.Parse(drugie.Text); int c = a + b; wynik.Text = c.ToString();}
• pierwsze.Text – zawartość pola tekstowego• int.Parse(...) – konwersja tekstu na liczbę• c.ToString() – konwersja zmiennej na tekst
34/34