Při tvorbě jakýchkoli aplikací narazíte čas od času na problém, že zobrazení určitých komponent či grafického prvku je známo až za běhu aplikace. V praxi tato situace může například nastat, když tvoříte anketu a máte otázku: Kouříte? Jako odpověď máte dva RadioButtony a po zvolení „Ano“ bude chtít zobrazit textové pole s popiskem: Jakou značku cigaret?
Pokud chcete vytvořit v Silverlightu jakoukoli komponentu, máte dvě možnosti. První možností je definování v XAMLu a druhou definování v kódu aplikace (Visual Basic, C#). Pokud se podíváme do knihovny MSDN na jakoukoli komponentu (např. CheckBox
), vždy nalezneme ukázku jak komponentu vytvořit v obou případech.
Jak na to?
Pojďme si na jednoduchém příkladu ukázat, jakou strukturu má zápis komponenty v C#. Vytvoříme si CheckBox
, který bychom jinak zapsali v XAMLu následovně:
<CheckBox x:Name="cb"
Content="Označ mě!"
FontFamily="Times New Roman"
FontSize="14"/>
Kód v C# bude vypadat takto:
CheckBox cb = new CheckBox();
cb.Content = "Označ mě!";
cb.FontFamily = new FontFamily("Times New Roman");
cb.FontSize = 14;
Struktura zápisu je jednoduchá. Nejprve vytvoříme instanci třídy CheckBox
a následně definujeme její atributy. Je nutné dávat pozor na typy atributů, jelikož některé z nich jsou definované pomocí jiného objektu nebo výčtu (enumeration). V ukázce je to vidět například u definice fontu. Dále se s tím setkáte například u definice barvy ( Colors.Orange
) nebo u definování stylu písma ( FontStyles.Italic
).
Zařazení
Dalším krokem při definování komponent je jejich zařazení. Když tvoříte komponentu v XAMLu a chcete aby byla zařazena v nějaké tabulce, Canvasu
nebo StackPanelu
, vytvoříte jí prostě uvnitř daného prvku.
Pokud však tvoříte komponenty z logiky musíte nějak říci dané komponentě do jakého „kontejneru“ patří. To uděláme pomocí zápisu:
LayoutRoot.Children.Add(cb);
Definování cizích (nevlastních) atributů
Stejně tak jako v XAMLu definujeme například zařazení do tabulky pomocí atributů GridRow a GridColumn přímo v těle komponenty, musíme i v C# tyto atributy definovat. Zápis se trochu liší, jelikož atributy GridRow a GridColumn nejsou vlastními atributy komponenty. Definujeme je tedy pomocí metody SetValue()
.
XAML:
<CheckBox x:Name="cb"
Content="Označ mě!"
FontFamily="Times New Roman"
FontSize="14"
Grid.Column="1"
Grid.Row="1"/>
C#:
CheckBox cb = new CheckBox();
cb.Content = "Označ mě!";
cb.FontFamily = new FontFamily("Times New Roman");
cb.FontSize = 16;
cb.FontStyle = FontStyles.Italic;
cb.SetValue(Grid.RowProperty, 1);
cb.SetValue(Grid.ColumnProperty, 1);
Podobně by to vypadalo i v případě Canvasu:
CheckBox cb = new CheckBox();
cb.Content = "Označ mě!";
cb.FontFamily = new FontFamily("Times New Roman");
cb.FontSize = 16;
cb.FontStyle = FontStyles.Italic;
cb.SetValue(Canvas.TopProperty, 10);
cb.SetValue(Canvas.LeftProperty, 10);
Příklad
Pokud budeme chtít, můžeme si dynamicky vytvořit i celý formulář společně s tabulkou, kterou použijeme pro rozložení formuláře:
//tabulka
Grid gr = new Grid();
gr.Height = 300;
gr.Width = 600;
//definice radku
RowDefinition rd1 = new RowDefinition();
rd1.Height = new GridLength(30);
RowDefinition rd2 = new RowDefinition();
rd2.Height = new GridLength(30);
//prirazeni definice
gr.RowDefinitions.Add(rd1);
gr.RowDefinitions.Add(rd2);
//definice sloupcu
ColumnDefinition cd1 = new ColumnDefinition();
cd1.Width = new GridLength(100);
ColumnDefinition cd2 = new ColumnDefinition();
cd2.Width = new GridLength(500);
//prirazeni definice
gr.ColumnDefinitions.Add(cd1);
gr.ColumnDefinitions.Add(cd2);
//vutvoreni a vlozeni komponent
//Jmeno
TextBlock tb_jmeno = new TextBlock();
tb_jmeno.Text = "Jméno a Příjmení:";
tb_jmeno.HorizontalAlignment = HorizontalAlignment.Right;
tb_jmeno.SetValue(Grid.ColumnProperty, 0);
tb_jmeno.SetValue(Grid.RowProperty, 0);
TextBox tbx_jmeno = new TextBox();
tbx_jmeno.SetValue(Grid.ColumnProperty, 1);
tbx_jmeno.SetValue(Grid.RowProperty, 0);
//Pohlavi
TextBlock tb_pohlavi = new TextBlock();
tb_pohlavi.Text = "Pohlaví:";
tb_pohlavi.HorizontalAlignment = HorizontalAlignment.Right;
tb_pohlavi.SetValue(Grid.ColumnProperty, 0);
tb_pohlavi.SetValue(Grid.RowProperty, 1);
//vytvoreni StackPanelu pro razeni
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
sp.SetValue(Grid.ColumnProperty, 1);
sp.SetValue(Grid.RowProperty, 1);
RadioButton rb_muz = new RadioButton();
rb_muz.Content = "muž";
rb_muz.GroupName = "pohlavi";
sp.Children.Add(rb_muz);
RadioButton rb_zena = new RadioButton();
rb_zena.Content = "žena";
rb_zena.GroupName = "pohlavi";
sp.Children.Add(rb_zena);
//prirazeni vsech komponent do tabulky
gr.Children.Add(tb_jmeno);
gr.Children.Add(tbx_jmeno);
gr.Children.Add(tb_pohlavi);
gr.Children.Add(sp);
Ve zdrojovém kódu si můžeme všimnout způsobu tvorby řádků a sloupců v tabulce. Nejprve si vytvoříme tabulku a následně si vytvoříme objekty definice řádků a sloupců, které následně přiřadíme k tabulce.
Události
Ukázali jsme si, jak dynamicky vytvářet komponenty a jak je vkládat do „kontejnerů“. Ale nastanou i případy, kdy po dané vygenerované komponentě budeme chtít, aby něco vykonávala. Pojďme si to ukázat na jednoduchém příkladu, kdy si vytvoříme v XAMLu tlačítko, při jehož stisknutí se vygeneruje další tlačítko, které na stisknutí vygeneruje text.
XAML:
<StackPanel x:Name="LayoutRoot"
Background="White"
Orientation="Vertical">
<Button x:Name="bt_xaml"
Content="Vygeneruj tlačítko"
Width="150"
Height="25"
Click="bt_xaml_Click"/>
</StackPanel>
C#:
private void bt_xaml_Click(object sender, RoutedEventArgs e)
{
//tlacitko pro vygenerovani textu
Button bt = new Button();
bt.Content = "Vygeneruj text";
bt.Width = 150;
bt.Height = 25;
bt.Click += new RoutedEventHandler(bt_Click);
LayoutRoot.Children.Add(bt);
}
void bt_Click(object sender, RoutedEventArgs e)
{
TextBlock tb = new TextBlock();
tb.Text = "Toto je vygenerovaný text.";
tb.Width = 150;
tb.TextWrapping = TextWrapping.Wrap;
tb.FontFamily = new FontFamily("Times New Roman");
tb.Foreground = new SolidColorBrush(Colors.Orange);
LayoutRoot.Children.Add(tb);
}
Principem je přiřazení metody k události na komponentě ( bt.Click += new RoutedEventHandler(bt_Click);
).
Závěrem
Pokud budete chtít tvořit aplikace v Silverlightu, této problematice se dozajista nevyhnete. Zvláště pokud se pustíte do tvorby her, kde je podmíněné generování komponent zcela běžné.
Faktem je, že tvorba komponent z logiky aplikace v C# nebo Visual Basicu není tak pohodlná, jako když je píšeme v XAMLu. Je tomu tak především ze dvou důvodů:
- musíme pamatovat na to, jaké atributy jsou jakého typu (jestli jsou objekt, výčet či text)
- musíme každou komponentu přiřazovat do „kontejneru“ namísto přímého vnoření jako v XAMLu
Pokračování přístě
V příštím článku se blíže podíváme na práci s médii, konkrétně pak na práci s videem.
Přehled komentářů