Sunteți pe pagina 1din 15

Laborator 2 – Introducere in WPF

Windows Presentation Foundation este un framework UI (User Interface) pentru crearea de


aplicatii client desktop. Platforma de dezvoltare WPF acceptă un set larg de caracteristici de
dezvoltare a aplicațiilor, inclusiv un model de aplicație, resurse, controale, grafică, aspect,
legatura de date, documente și securitate. WPF utilizează limbajul XAML (Extensible
Application Markup Language) pentru a furniza un model declarativ pentru programarea
aplicațiilor.
Nucleul WPF este un motor de randare vectorial, resolution-independent care este construit
pentru a profita de avantajele hardware-ului grafic modern.

Markup & code-behind


WPF permite dezvoltarea aplicatiilor la ambele nivele: markup si code-behind. In general se
foloseste XAML markup pentru implementarea interfetei aplicatiei si limbajul de programare
managed (code-behind) pentru implementarea comportamentului acesteia.
Aceasta separatie intre interfata si comportament are urmatoarele avantaje:
 Costurile de dezvoltare si mentenanta sunt reduse, intrucat codul markup din interfata
nu este strans legat de codul sursa specific comportamentului
 Procesul de dezvoltare este mai eficient, intrucat designerii pot implementa interfata cu
utilizatorul in acelasi timp in care programatorii dezvolta codul sursa
 Globalizarea si localizarea aplicatiilor WPF sunt simplificate

1. XAML Introduction
XAML este un limbaj declarativ de markup. Așa cum este aplicat modelului de programare
.NET Framework, XAML simplifică crearea unui UI pentru o aplicație .NET Framework. Puteți
crea elemente de interfață UI vizibile în limbajul declarativ XAML și apoi sa separați definiția
UI de logica programului din fisierele ce contin codul sursa.
Prima aplicatie WPF
Din meniul File -> New -> Project selectati WPF App (.NET Framework).

Prima fereastra care apare este MainWindow.xaml.

In cadrul ferestrei se observa o clasa, cateva namespace-uri, un titlu si proprietatile ferestrei


care determina dimensiunile acesteia. In cadrul ferestrei se gaseste un panou de tip Grid, care
apare implicit la crearea oricarei aplicatii.
Din fereastra Toolbox vom adauga un TextBlock in care vom scrie mesajul „Hello WPF!”.
Grid Rows & Columns
Creati o noua aplicatie WPF numita LayoutWithGrids.
Observati ca fereastra are setate anumite valori pentru inaltime si latime, proprietati ce
reprezinta constrangeri pentru Grid. Un grid este compus din randuri (row) si coloane (columns)
care pot fi instantiate prin crearea de RowDefinitions si ColumnDefinitions.
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition />
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

Fiecare obiect RowDefinition poate definit inaltimea unui rand prin mai multe moduri. Una din
modalitati este proportionala, sau star-sizing. Valoarea implicita a inaltimii unui rand, este de o
*. Practic, inaltimea Grid-ului se va imparti la numarul de stelute, iar inaltimea fiecarui rand va
depinde de numarul de stelute definit.
<Rectangle Fill="Red" Grid.Row="0" />
<Rectangle Fill="Orange" Grid.Row="1"/>
<Rectangle Fill="Yellow" Grid.Row="2" />
<Rectangle Fill="Green" Grid.Row="3"/>
<Rectangle Fill="Blue" Grid.Row="4" />
<Rectangle Fill="Indigo" Grid.Row="5"/>

Alte modalitati de a seta inaltimea unui rand sunt prin a specifica explicit valoarea acesteia in
device independent pixels, sau prin setarea valorii Auto, care calculeaza inaltimea in functie de
celelalte elemente din Grid.
Pentru adaugarea coloanelor, vom crea ColumnDefinitions.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
Vom rearanja dispunerea dreptunghiurilor.

<Rectangle Fill="Red" Grid.Row="0" />


<Rectangle Fill="Orange" Grid.Row="0" Grid.Column="1"/>
<Rectangle Fill="Yellow" Grid.Row="1" />
<Rectangle Fill="Green" Grid.Row="1" Grid.Column="1"/>
<Rectangle Fill="Blue" Grid.Row="2" />
<Rectangle Fill="Indigo" Grid.Row="2" Grid.Column="1"/>
<Rectangle Fill="Violet" Grid.Row="3" />
<Rectangle Fill="Black" Grid.Row="3" Grid.Column="1"/>

Adaugati un label:
<Label Content="Rectangles showing column width"
FontSize="24"
Grid.Row="4" />

Se observa ca textul este limitat doar la nivelul primei celule din rand.
<Label Content="Rectangles showing column width"
FontSize="24"
Grid.Row="4"
Grid.ColumnSpan="2"/>
<Rectangle Fill="Wheat"
Grid.Row="5" />
<Rectangle Fill="Purple"
Grid.Row="5"
Grid.Column="1" />
StackPanel
Creati o noua aplicatie WPF: LayoutWithStackPanel. Un StackPanel permite aranjarea
obiectelor sub forma unei stive.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="Your Name" Margin="5"/>
<TextBox Width="80" Height="Auto" Margin="5"/>
</StackPanel>
</Grid>

WrapPanel
Un WrapPanel plaseaza obiectele unl langa celalalt pana cand nu mai incap in panou, apoi
creeaza un al doilea rand de obiecte continuand dupa aceeasi structura.
<WrapPanel>
<Rectangle Fill="Red" Width="50" Height="50" />
<Rectangle Fill="Orange" Width="50" Height="50" />
<Rectangle Fill="Yellow" Width="50" Height="50" />
<Rectangle Fill="Green" Width="50" Height="50" />
<Rectangle Fill="Blue" Width="50" Height="50" />
<Rectangle Fill="Indigo" Width="50" Height="50" />
<Rectangle Fill="Violet" Width="50" Height="50" />
<Rectangle Fill="Red" Width="50" Height="50" />
<Rectangle Fill="Orange" Width="50" Height="50" />
<Rectangle Fill="Yellow" Width="50" Height="50" />
<Rectangle Fill="Green" Width="50" Height="50" />
<Rectangle Fill="Blue" Width="50" Height="50" />
<Rectangle Fill="Indigo" Width="50" Height="50" />
<Rectangle Fill="Violet" Width="50" Height="50" />
</WrapPanel>
Orientarea implicita a unui WrapPanel este orizontala. Schimati orientarea panoului curent pe
verticala: Orientation="Vertical".

DockPanel
Obiectele dintr-un DockPanel se aliniaza dupa o anumita orientare.
<DockPanel>
<Button Height="25"
Background="Red"
DockPanel.Dock="Top" />
<Button Width="25"
Background="Orange"
DockPanel.Dock="Left" />
<Button Width="25"
Background="Yellow"
DockPanel.Dock="Right" />
<Button Height="25"
Background="Green"
DockPanel.Dock="Bottom" />
<Button Background="Purple" />
</DockPanel>
Canvas
Obiectele dintr-un Canvas se aliniaza dupa o pozitie absoluta.
<Canvas>
<Rectangle Canvas.Left="25"
Canvas.Top="25"
Width="50"
Height="40"
Fill="Red" />

<Rectangle Canvas.Left="100"
Canvas.Top="25"
Width="50"
Height="40"
Fill="Orange" />

<Rectangle Canvas.Left="125"
Canvas.Top="40"
Width="50"
Height="40"
Fill="Blue" />

<Ellipse Canvas.Left="25"
Canvas.Top="200"
Width="40"
Height="40"
Fill="Green" />
</Canvas>
Controls
Controalele sunt mercanisme on-screen care afiseaza si colecteaza informatia de la utilizator.
In mare acestea se clasifica in:
 Text Controls
 Selection Controls
 List Controls
 Other Controls

Pentru trecerea in revista a controalelor, vom crea un formular simplu. Creati o noua aplicatie
WPF: SimpleFormApp.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBlock Text="Full Name"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="5" />
<TextBox Grid.Column="1"
Name="FullName"
Width="250"
Height="20"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Margin="5" />
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="5"
Grid.Row="1"
TextWrapping="Wrap"
Text="Sex" />
<StackPanel Orientation="Horizontal"
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<RadioButton GroupName="Sex" Name="Male" Content="Male" IsChecked="True"
Margin="5" />
<RadioButton GroupName="Sex" Name="Female" Content="Female" IsChecked="False"
Margin="5" />
</StackPanel>
<TextBlock Text="Do you own"
Grid.Row="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="5" />
<StackPanel Orientation="Horizontal"
Grid.Row="2"
Grid.Column="2"
VerticalAlignment="Bottom"
HorizontalAlignment="Left">
<CheckBox Name="Desktop" Content="Desktop" Margin="5" />
<CheckBox Name="Laptop" Content="Laptop" Margin="5" />
<CheckBox Name="Tablet" Content="Tablet" Margin="5" />
</StackPanel>
<TextBlock Text="Your job"
Grid.Row="3"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="5" />
<ComboBox Grid.Row="3"
Name="Job"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Margin="5">
<ComboBoxItem Content="Programmer" />
<ComboBoxItem Content="Designer" />
<ComboBoxItem Content="Architect" />
<ComboBoxItem Content="Manager" />
<ComboBoxItem Content="Seller" />
</ComboBox>
<TextBlock Text="Promissed delivery date"
Grid.Row="4"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="5" />
<Calendar Grid.Row="4"
Name="DeliveryDate"
Grid.Column="1"
Margin="5"
HorizontalAlignment="Left" />
</Grid>
In momentul de fata, aplicatia afiseaza un formular static. In continuare vom dezvolta logica
aplicatiei, pentru colectarea datelor de la utilizator si afisarea lor intr-un MessageBox.

Events
Vom adauga un buton imediat dupa obiectul Calendar din Grid.
<Button Content="Save"
Name="SaveButton"
Grid.Row="5"
Margin="5"
HorizontalAlignment="Right"
Click="SaveButton_Click" />

Putem defini un eveniment prin fereastra de proprietati ale butonului, sau scriindu-l direct in
codul XAML. In clasa MainWindow s-a creat automat evenimentul:
private void SaveButton_Click(object sender, RoutedEventArgs e)

Pentru afisarea informatiilor, vom crea un obiect StringBuilder si vom adauga datele introduce
de utilizator.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("Full Name: ");
stringBuilder.Append(FullName.Text);
stringBuilder.Append(" Sex: ");
stringBuilder.Append( (bool) Male.IsChecked ? "Male" : "Female");
stringBuilder.Append( " Computer: ");
stringBuilder.Append((bool)Desktop.IsChecked ? "Desktop" : "");
stringBuilder.Append((bool)Laptop.IsChecked ? "Laptop" : "");
stringBuilder.Append((bool)Tablet.IsChecked ? "Tablet" : "");
stringBuilder.Append(" Your job: ");
stringBuilder.Append(Job.SelectedItem.ToString());
stringBuilder.Append(" Delivery date: ");
stringBuilder.Append(DeliveryDate.SelectedDate.ToString());

MessageBox.Show(stringBuilder.ToString());

In momentul de fata informatiile nu sunt citite corect din obiectul ComboBox.


Adaugati obiectului XAML proprietatea: SelectionChanged="Job_SelectionChanged".
In MainWindow s-a creat deja evenimentul:
private void Job_SelectionChanged(object sender, SelectionChangedEventArgs e)

Completati codul de gestiune al evenimentului:


var newlySelectedItem = e.AddedItems[0];
MessageBox.Show(newlySelectedItem.ToString());
2. Data binding

2.1 Data binding one way


Creati o noua aplicatie WPF: DataBindingOneWay. In cadrul acestei aplicatii vom exemplifica
modul de aducere al datelor din back-end si dispunerea lor in interfata cu utilizatorul.
Adaugati o noua clasa Employee.
public class Employee
{
public string Name { get; set; }
public string Title { get; set; }

public static Employee GetEmployee()


{
return new Employee
{
Name = "John",
Title = "Developer"
};
}
}

In MainWindow.xaml:
<Grid>
<StackPanel Name="Display">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: " />
<TextBlock Margin="5,0,0,0" Text="{Binding Name}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Title: " />
<TextBlock Margin="5,0,0,0" Text="{Binding Title}" />
</StackPanel>
</Grid>

Legatura de date se face prin in clasa MainWindow:


DataContext = Employee.GetEmployee();

2.2 INPC
Este posibil ca mai mult de o persoana sa modifice datele. Clasa Employee trebuie sa
implementeze interfata INotifyPropertyChanged.
public class Employee : INotifyPropertyChanged
{
private string _name;
private string _title;

public string Name


{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}

public string Title


{
get
{
return _title;
}
set
{
_title = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string caller = "")


{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}

public static Employee GetEmployee()


{
var emp = new Employee()
{
Name = "Tom",
Title = "Developer"
};
return emp;
}
}

In MainWindow.xaml adaugam un buton:


<Button Content="Change"
Click="Button_Click" />

MainWindow.cs:
public partial class MainWindow : Window
{
private Employee _employee;

public MainWindow()
{
InitializeComponent();
_employee = new Employee()
{
Name = "John",
Title = "Developer"
};
DataContext = _employee;
}

private void Button_Click(object sender, RoutedEventArgs e)


{
_employee.Name = "Dave";
_employee.Title = "Manager";
}
}

2.3 Data Binding TwoWay


Pentru urmatorul exemplu, vom porni de la proiectul anterior si vom modifica interfata cu
utilizatorul adaugand cateva elemente de interactune cu utilizatorul.
<Grid>
<StackPanel Name="Display">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: " />
<TextBox Margin="5,0,0,0" Text="{Binding Name, Mode=TwoWay}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Title: " />
<TextBox Margin="5,0,0,0" Text="{Binding Title, Mode=TwoWay}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: " />
<TextBlock Margin="5,0,0,0" Text="{Binding Name}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Title: " />
<TextBlock Margin="5,0,0,0" Text="{Binding Title}" />
</StackPanel>
</StackPanel>
</Grid>

2.4 Data Binding Lists


Creati un nou proiect WPF: DataBindingLists.
Vom adauga o clasa Employee.
Pentru a notifica View-ul de eventualele modificari din lista, avem nevoie de clasa
ObservableCollection. Practic este o colectie de obiecte ce implementeaza
INotifyPropertyChanged.
public class Employee : INotifyPropertyChanged
{
private string _name;
private string _title;

public string Name


{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}

public string Title


{
get
{
return _title;
}
set
{
_title = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string caller = "")


{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}

public static Employee GetEmployee()


{
var emp = new Employee()
{
Name = "Tom",
Title = "Developer"
};
return emp;
}

public static ObservableCollection<Employee> GetEmployees()


{
var employees = new ObservableCollection<Employee>();
employees.Add(new Employee() { Name = "Dave", Title = "Manger" });
employees.Add(new Employee() { Name = "John", Title = "Developer" });
employees.Add(new Employee() { Name = "Anna", Title = "Recruiter" });
employees.Add(new Employee() { Name = "Jack", Title = "Analyst" });
employees.Add(new Employee() { Name = "Duncan", Title = "Architect" });

return employees;
}
}

MainWindow.cs: DataContext = Employee.GetEmployees();

MainWindow.xaml:
<Grid>
<ComboBox Name="Presidents" ItemsSource="{Binding}" FontSize="30" Height="50"
Width="550">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Name: "
Margin="2" />
<TextBlock Text="{Binding Name}"
Margin="2" />
<TextBlock Text="Title: "
Margin="10, 2, 0, 2" />
<TextBlock Text="{Binding Title}"
Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>

2.5 Data Binding to an Element


<Grid>
<StackPanel Orientation="Horizontal">
<Slider Name="mySlider"
Minimum="0"
Maximum="100"
Width="300" />
<TextBlock Margin="5" Text="{Binding Value, ElementName=mySlider}" />
</StackPanel>
</Grid>

S-ar putea să vă placă și