Proprietati comunne in WPF:
| Proprietate + ex valoare | Tip data |
| Background=”#FFD5FCFC” | Brush |
| Cursor=”Pen” | Cursor |
| FlowDirection=”RightToLeft” | enum |
| Focusable=”True” | bool |
| FontFamily=”Times New Roman” | FontFamily |
| FontSize=”16″ | double |
| FontStretch=”Normal” | struct FontStretch |
| FontStyle=”Italic” | struct FontStyle |
| FontWeight=”Bold” | struct FontWeight |
| Foreground=”Aquamarine” | Brush |
| ForceCursor=”False” | bool |
| HorizontalAlignment=”Center” | enum |
| Margin=”5″ | Thickness |
| MinHeight=”50″ | double |
| MinWidth=”20″ | double |
| Opacity=”0.8″ | double |
| Padding=”5″ | Thickness |
| Panel.ZIndex=”3″ | dependency prop |
| Tag=”object” | object |
| Text=”aaaaaaa” | string |
| VerticalAlignment=”Center” | enum |
In mod normal ar fi trebuit sa discut diverse proprietati grupate dupa clasa din care deriva componentele, insa am decis sa procedez un pic diferit. Proprietatile de mai sus nu sunt comune tuturor componentelor (de exemplu, Rectangle nu are o proprietate Padding), insa sunt suficient de comune si fiecare proramator ar trebui, inainte de a incepe sa construiasca cu ajutorul componentelor WPF, sa stie cum se folosesc.
Asadar, o sa le iau pe rand:
Background – stabileste culoarea de fundal. Aceasta proprietate este de tip Brush, ceea ce inseamna ca putem crea, cu ajutorul Brush, efecte foarte interesante. Cel mai simplu Brush este SolidColorBrush, o “pensula” care coloreaza cu o culoare uniforma. Insa mai sunt si altele:

Voi arata pe scurt, urmand sa revin cu mai multe detalii in viitor, cum se pot crea unele dintre aceste tipuri de pensula (Brush):
SolidColorBrush myBrush = new SolidColorBrush(Colors.Red);
Codul de mai sus va crea o pensula cu ajutorul caruia putem colora in rosu (Colors.Red). Sa presupunem ca vreau sa desenez un dreptunghi rosu. Voi folosi XAML pentru asta:
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <SolidColorBrush Color="Red" /> </Rectangle.Fill> </Rectangle>
Codul de mai sus imi va desena:

LinearGradient este un tip de pensula care imi permite sa colorez anumite suprafete (sau contururi) folosind mai multe culori, culori care au o trecere uniforma liniara de la una la alta. Exemplu:
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <LinearGradientBrush> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Orange" Offset="0.5" /> <GradientStop Color="Red" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Care va desena:

Pentru a obtine acelasi rezultat insa fara a folosi XAML ar trebui scris urmatorul cod c#:
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a LinearGradientBrush and use it to // paint the rectangle. LinearGradientBrush myBrush = new LinearGradientBrush(); myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0)); myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5)); myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0)); exampleRectangle.Fill = myBrush;
Cursor: – forma cursorului in momentul in care acest este deasupra elementului curent. Pentru a vedea cum arata fiecare cursor voi folosi o aplicatie simpla. Cu ajutorul acestei aplicatii voi demonstra si alte proprietati. Ce vreau sa fac? O aplicatie care sa contine un tabel cu 2 coloane, iar fiecare rand sa contina numele cursorului – celula din stanga, si un panel – celula din dreapta, care sa aiba setata proprietatea Cursor corespunzator textului din celula din partea stanga.
In acest exemplu vom recapitula si cate ceva despre controalele descrse in capitolul anterior. La inceput voi crea un nou proiect, de tip WPF. Am numit acest proiect CommonProps. Pentru inceput voi edita fisierul MainWindow.xaml (daca nu este deschis, dublu click pe numele fisierului in fereastra Solution Explorer). In mod prestabilit XAML-ul acestei ferestre contine un Grid. Acest nu prea este potrivit pentru ceea ce am eu de gand sa construisc, motiv pentru care il voi inlocui cu altceva: un ScrollViewer care va contine un UniformGrid. Deasemeni voi schimba putin si fereastra, regimensionand-o si blocand redimensionarea. Codul XAML este urmatorul:
<Window x:Class="CommonProps.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Common Properties" Height="350" Width="225" ResizeMode="NoResize"> <ScrollViewer> <UniformGrid Columns="2" x:Name="grid"> </UniformGrid> </ScrollViewer> </Window>
Ce avem? O fereastra de dimensiune 350 x 225, fara posibilitatea de redimensionare (ResizeMode=”NoResize”). Continutul acestei ferestre este un ScrollViewer, care are rolul de a ne da barele de derulare in cazul in care continutul va fi mai lung decat suprafata vizibila a ferestrei. Acest element contine un container de tip UniformGrid care are rolul de a gazdui tot ceea ce vom adauga in aplicatie. Asa cum se vede din XAML, UniformGrid are doua coloane, in coloana din stanga voi gazdui numele cursorului iar in cea din dreatpa un Panel caruia ii voi seta proprietatea Cursor corespunzator cu numele afisat in acelasi rand in celula din stanga. Fara nimic altceva fereastra aplicatiei arata asa:

Am observat ca in .Net exista o clasa factory pentru cursoare. Aceasta clasa se numeste Cursors, care are cateva proprietati statice, fiecare returnand un obiect de tip Cursor. Pentru a obtine aceste proprietati ca si lista de string voi folosi Reflection, intr-o metoda separata:
private string[] GetCursors()
{
PropertyInfo[] propertyInfos;
propertyInfos = typeof(Cursors).GetProperties(BindingFlags.Public | BindingFlags.Static);
if (propertyInfos == null)
return null;
string[] strProps = new string[propertyInfos.Length];
for (int i = 0; i < propertyInfos.Length; i++)
{
strProps[i] = propertyInfos[i].Name;
}
return strProps;
}
Tocmai am “obtinut” continutul coloanei din stanga. Pentru coloana din dreapta voi folosi un StackPanel, caruia as vrea, pentru a-l vedea mai bine, sa ii setez o culoare de fundal, random. Pentru asta am nevoie de inca o metoda ajutatoare care sa imi genereze o astfel de culoare:
Random r = new Random();
private Color GetRandomColor()
{
return Color.FromRgb((byte)r.Next(0, 256), (byte)r.Next(0, 256), (byte)r.Next(0, 256));
}
Pentru fiecare panel as fi vrut sa setez proprietatea Cursor folosind reflection, insa as complica (cred eu) inutil codul, asa ca am sa setez aceasta proprietate direct, folosing o metoda ajutatoare, care primest un nume de cursor si returneaza un obiect Cursor. Aceasta metoda foloseste un switch pentru a face asta. Recunosc, nu e frumos, insa nu as vrea sa intru in detalii de Reflection, scopul actual fiind WPF.
Tot codul pe care il voi scrie (pana acum) in MainWindow.xaml.cs este urmatorul (contine si metodele descrise anterior):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Reflection; namespace CommonProps { public partial class MainWindow : Window { Random r = new Random(); public MainWindow() { InitializeComponent(); PopulateGrid(); } private void PopulateGrid() { string[] cursors = GetCursors(); if (cursors == null) return; for (int i = 0; i < cursors.Length; i++) { TextBlock tb = new TextBlock(); tb.Text = cursors[i]; Panel p = new StackPanel(); p.Cursor = ParseCursor(cursors[i]); p.MinHeight = p.MinWidth = 10; p.Background = new SolidColorBrush(GetRandomColor()); grid.Children.Add(tb); grid.Children.Add(p); } } private string[] GetCursors() { PropertyInfo[] propertyInfos; propertyInfos = typeof(Cursors).GetProperties(BindingFlags.Public | BindingFlags.Static); if (propertyInfos == null) return null; string[] strProps = new string[propertyInfos.Length]; for (int i = 0; i < propertyInfos.Length; i++) { strProps[i] = propertyInfos[i].Name; } return strProps; } private Cursor ParseCursor(string name) { switch (name) { case "AppStarting": return Cursors.AppStarting; case "ArrowCD": return Cursors.ArrowCD; case "Arrow": return Cursors.Arrow; case "Cross": return Cursors.Cross; case "HandCursor": return Cursors.Hand; case "Help": return Cursors.Help; case "IBeam": return Cursors.IBeam; case "No": return Cursors.No; case "None": return Cursors.None; case "Pen": return Cursors.Pen; case "ScrollSE": return Cursors.ScrollSE; case "ScrollWE": return Cursors.ScrollWE; case "SizeAll": return Cursors.SizeAll; case "SizeNESW": return Cursors.SizeNESW; case "SizeNS": return Cursors.SizeNS; case "SizeNWSE": return Cursors.SizeNWSE; case "SizeWE": return Cursors.SizeWE; case "UpArrow": return Cursors.UpArrow; case "WaitCursor": return Cursors.Wait; default: return null; } } private Color GetRandomColor() { return Color.FromRgb((byte)r.Next(0, 256), (byte)r.Next(0, 256), (byte)r.Next(0, 256)); } } }
La rulare vom vedea urmatoarea fereastra (culorile din dreapta difera la fiecare executie, sunt random generate):

Cand cursorul mouseului intra peste un panel, vizibil datorita culori de fundal, din coloana din dreapta, el isi schimba forma. Asa putem vedea toate tipurile de cursor predefinite (pot fi folosite si cursoare definite de user, insa nu voi intra in detalii referitor la asta). In aceasta aplicatie am demonstrat si folosirea proprietatii Background. In continuare voi “imbunatati” aplicatia pentru a demonstra folosirea tuturor proprietatilor de la inceputul acestui capitol.
FlowDirection: este utila in cazul in care textul este scris intr-o limba care se citeste (scrie) de la dreapta la stanga, cum ar fi hebrew sau araba. In mod default valoarea FlowDirection este LeftToRight. Pentru a inversa (hebrew, araba etc) vom folosi RightToLeft. Aceste valori sunt de tip enum: System.Windows.FlowDirection.
Focusable: permite sau suprima posibilitatea ca un element sa primeasca focus. Unele controale au aceasta proprietate default setata la true, altele false. In exemplul anterior, in coloana din dreapta a grid-ului avem elemente de tip StackPanel; aceste elemente nu permit focus in mod prestabilit. Daca in codul de mai sus adaugam urmatoarea linie:
p.Focusable = true;
atunci la apasarea reetata a tastei Tab vom obtine focus, pe rand, pe fiecare panel.
FontFamily, FontSize, FontStretch, FontStyle, FontWeight – toate se refera la diverse proprietati ale fontului, daca este cazul – de exemplu, in cazul unui obiect de tip Shape, nu e cazul. Daca avem un buton, putem sa stabilim parametrii textului folosind aceste proprietati. Daca avem o structura ierarhica (parinte – copil), WPF foloseste in cazul in care o proprietate nu a fost definita in elementul copil proprietatea elementului parinte. De exemplu, daca avem un buton care are Content un TextBlock. Definim in Button proprietatea FontSize = “18”. Aceasta, daca nu am definit acceasi proprietate si pentru TextBlock se transmite acestuia:
<Button FontSize="18">
<TextBlock>13131</TextBlock>
</Button>
va desena un buton al carui continut va fi desenat folosind un font de dimensiune 18.
Revenind la aplicatia noastra, voi folosi completa codul astfel incat fontul folosit in coloana din stanga sa primeasca niste setari suplimentare:
TextBlock tb = new TextBlock();
tb.Text = cursors[i];
tb.FontFamily = new FontFamily("Comic Sans MS");
tb.FontSize = 14;
tb.FontStretch = FontStretches.Expanded;
tb.FontStyle = FontStyles.Italic;
tb.FontWeight = FontWeights.Bold;
Foreground – este o proprietate de tip Brush. Aceasta da felul cum textul este desenat. Aceasta proprietate este similara cu Background, tipul fiind acelasi.
ForceCursor – in mod prestabilit este false – insa daca este setata true aceasta forteaza desenarea cursorului cand acesta se afla deasupra controlului curent conform proprietatii Cursor. Aceasta este utila pentru a modifica comportamentul cursorului mouseului care raspunde nu numai aplicatiei noastre ci si sistemului de operare.
HorizontalAlignment si VerticalAlignment – stabileste modul cum continutul este aliniat in raport cu marginile laterale sau verticale. Aceasta proprietate este de tip enum. O valoare interesanta pentru aliniere este Stretch. Aceasta este echivalentul (sa zicem) al Justify din editoarele de texte. Cu alte cuvinte aceasta forteaza (atunci cand continutul suporta) continutul sa ocupe tot spatiul disponibil. Pentru multe controale Stretch este valoarea prestabilita a proprietatilor de aliniere.
Margin si Padding sunt proprietati de tip Thickness. Margin stabileste distanta dintre control si container (sau elementul aflat pe acelasi nivel in containerele care permit mai multe elemente copil). Padding stabileste distanta dintre conturul elementului si continutul acestuia. Daca ne imagimam un element ca fiind un dreptunghi, atunci avem:

Continutul este ceea ce se vede in mijloc, dreptunghiul mic. In jurul lui avem un spatiu care reprezinta padding. Apoi (daca este cazul) urmeaza un contur care delimiteaza (granita) elementului. In jur avem Margin, ceea ce reprezinta distanta dintre element si elementele inconjuratoare/vecine. Atat Margin, cat si Padding, pot primi valori diferite pentru cele 4 directii. Pot defini asa: Padding=”5 2 8 1″, ordinea este stanga (5), sus (2), dreapta (8) si jos (1). La fel si in cazul Margin.
MinHeight si MinWidth – odata definite rezerva un spatiu minim pentru element. Asta inseamna ca daca elementul curent are nevoie de un spatiu vertical X insa eu am setat MinWidth = “Y”, unde Y > X, atunci elementului ii va fi alocat un spatiu (width) de valoare Y. Daca spatiul ocupat este mai mare decat cel MinHeight, atunci MinHeight nu mai are relevanta in desenare. Acelasi lucru si pentru MinHeight.
Opacity – este o valoare de tip double care poate avea valori intre 0 si 1 (mai mic decat 0 sau mai mare decat 1 sunt automat “rotunjite” la 0, respectiv 1). O valoare de 0 inseamna control complet transparent, iar 1 insemna un control complet opac. Valorile intermediare ofera un grad corespunzator de transparenta.
ZIndex – o proprietate foarte importanta, de tip dependency property (despre acest tip voi scrie un capitol intreg), stabileste pozitia pe axa Z a elementului. Daca 2 elemente ocupa acelasi spatiu (de exemplu aceeasi celula intr-un Grid), ZIndex va stabili care element este desenat primul (care element este vizibil si care nu sau partial vizibil).
Tag – este o proprietate de tip object, fara utilizare specifica, insa care ne ofera posibilitatea de a pastra in elementul a carui proprietate Tag o definim, o referinta la un obiect necesar ulterior. Aplicatia urmatoare este un exemplu de folosire a acestei proprietati:
//ToDo: o aplicatie care sa comute o colectie de ceva, fiind posibil ca numai un element al colectiei sa aiba o anumita proprietate.
Text – pentru controalele care suporta, aceasta este modalitatea de a le atribui un text. Pentru a afisa textul pe mai multe randuri se foloseste “escape character” \n. Exemplu:
TextBlock txt = new TextBlock();
txt.Text = "Multumesc pentru vizitarea acestui site!\nAdy";
care va avea ca rezultat: 