Dynamicky generované komponenty v Silverlightu 2.0

V článku si na několika jednoduchých příkladech ukážeme, jak lze dynamicky vytvářet komponenty za běhu aplikace, a jak můžete s takovými komponentami pracovat. V jednotlivých příkladech si postup porovnáme s jejich tvorbu pomocí XAML.

Seriál: Praktické užití Silverlight 2.0 (12 dílů)

  1. Praktické užití Silverlight 2.0: Data Binding 15.12.2008
  2. Praktické užití Silverlight 2.0: DataGrid 22.12.2008
  3. Praktické užití Silverlight 2.0: UserControl 29.12.2008
  4. Co zajímavého přínáší Silverlight toolkit 5.1.2009
  5. Silverlight toolkit a vizualizace dat 12.1.2009
  6. Jak na komponenty AutoCompleteBox a TreeView ze Silverlight toolkitu 19.1.2009
  7. Nástroje pro tvorbu layoutu v Silverlightu 2.0 a Silverlight toolkitu 26.1.2009
  8. Design se styly a šablonami v Silverlightu 2.0 2.2.2009
  9. Základy 2D grafiky v Silverlightu 2.0 16.2.2009
  10. Dynamicky generované komponenty v Silverlightu 2.0 3.3.2009
  11. Úvod do streamování médií v Silverlightu 2.0 16.3.2009
  12. Práce s videem v Silverlightu 2.0 1.6.2009

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.

Zdroje

Používáte dynamicky generované komponenty?

Autor pracuje ve společnosti Sprinx Systems a.s. jako Project Manager ve „webařské“ skupině.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 5

Přehled komentářů

Štěpán Bechynský XamlReader
Jan Jelínek Re: XamlReader
Jiří Knesl Děkuji
Rene.Stein Popup v Silverlightu
janis Re: Popup v Silverlightu
Zdroj: https://www.zdrojak.cz/?p=2954