Stránky

Zobrazují se příspěvky se štítkemWPF. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemWPF. Zobrazit všechny příspěvky

pondělí 30. srpna 2010

Jak vytvořit vlastní tlačítka s obrázky za pomocí template ve WPF?

Jak vytvořit vlastní tlačítka s obrázky za pomocí template ve WPF?

Aby bylo možné jednoduše vytvořit tlačítko, kde při každém stavu je použitý jiný zdrojový obrázek, je zapotřebí vytvořit si vlastní template, která bude osahovat veškeré potřebné informace.

Začneme tím, že si v Blendu vložíme na layout klasický button. Ten nám možnost použití různých obrázků při různých stavech tlačítka (např. MouseOver,MouseClick,MouseLeftButtonDown) nenabízí a tak je zapotřebí kliknout pravým tlač. na to tlačítko/edit template/Create empty.



Po zvolení jména template a umístění se Vám zobrazí prázdný grid, kam nandáte potřebné elementy (obrázky).  Já použiji 3 různé obrázky pro defaultní stav, zmáčknutý stav a stav, kdy nelze mačkat (disabled stav).
 

Všechny 3 obrázky dám na stejnou pozici, nastavím stejnou velikost a další potřebné vlastnosti (zarovnání,Stretch….). Pro zobrazení Contentu na tlačítku ještě do gridu přidám ContentPresenter,  který automaticky binduje Content tlačítka, viz. níže. ContentPresenter nastavím na střed a dám mu automatickou velikost.

Nyní je zapotřebí nastavit chování tlačítka v jednotlivých stavech. V záložce Triggers je vidět, že se nacházíme ve stavu Default, takže necháme obrázku, který má být vidět visibilitu na visible a ostatním nastavíme na hidden. Poté přidáme v záložce Triggers novou Property, kde nastavíme target-element.isPressed = true (true je tam potřeba napsat). Nyní musíme nastavit visibilitu obrázku, který má být vidět při stisknutém tlačítku a ostatní musí být hidden. Poslední stav je stav Disabled, takže dáme zase v Triggers přidat Property, kde bude target-element.isEnabled = false a nastavíme obrázku,který má být vidět při disabled stavu visibilitu a ostatní dáme na hidden. Tím máme vytvořenou template pro vlastní tlačítka. Samozřejmě je možné jednotlivým stavům přiřadit třeba různé storyboardy na nějaké animace atd., ale to už je jen na Vás.

Celá template se nám uloží v XAML kódu do Window.Resources , kde jsou vidět naše všechny kroky a lze je jednoduše modifikovat.
Show/Hide
<ControlTemplate x:Key="ButtonControlImageBut" TargetType="{x:Type Button}">
<Grid Margin="0">
<Image x:Name="image1" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" Source="Images/butPressed.png" Stretch="Uniform" Visibility="Hidden"/>
<Image x:Name="image" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" Source="Images/butDefault.png" Stretch="Uniform"/>
<Image x:Name="image2" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" Source="Images/butDisabled.png" Stretch="Uniform" Visibility="Hidden"/>
<ContentPresenter Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Visible"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Visibility" TargetName="image" Value="Hidden"/>
<Setter Property="Visibility" TargetName="image1" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" TargetName="image2" Value="Visible"/>
<Setter Property="Visibility" TargetName="image" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>



Nyní se vrátíme tedy na hlavní layout, kde máme naše jedno tlačítko plně funkční (stisknutím tlač. Button, hned vedle Template). V Properties můžeme tlačítku nastavit požadovaný Content, font, velikost fontu atd. Když vložíme další tlačítko na layout, tak na něj dáme pravým tlač. a dáme EditTemplate/ApplyResource a zvolíme náš vlastní vytvořený ressource. Tímto způsobem můžeme templatu aplikovat na libovolné množství tlačítek.

I po nastavení isEnabled na false je vidět, že vše funguje jak má.

Další možnosti editace:
Celou template můžete v Xaml kódu zkopírovat a jednoduše použít templatu např. pro červené, modré a bílé tlačítka tím, že změníme název template a změníme imageSource cestu a je hotovo.
Pokud potřebujete použít na zobrazení Contentu tlačítek jinou kontrolu než je ContentPresenter, tak je možné použít třeba TextBlock a nastavit mu bindování Contentu, jinak by se nám tam požadovaný text nezobrazoval. Text="{TemplateBinding Content}"
Použití jednoho Storyboardu na více prvků najednou.


Pro názornou ukázku si na layout dám např. 5x TextBlock a vytvořím si jednoduchý Storyboard na prvním TextBlocku, který mi bude měnit barvu pozadí. Nyní se dostávám do situace, kdy ten Storyboard je jen pro ten jeden TextBlock. Já potřebuji, abych si v kódu zvolil, že se animace má provést na TextBlocku1, TextBlocku4 a TextBlocku5. Řešení je vcelku jednoduché. V Xaml kódu musíme odstranit Storyboard.TargetName="TB1" a tím máme Storyboard, který není přiřazen žádnému targetu. Pozor, pokud odstraníte TargetName, tak v Blendu již nelze upravovat samotný storyboard, jelikož hází chybu. Pokud jsou potřeba nějaké pozdější úpravy, tak si tam vždycky ten target musíte dopsat, vyzkoušet a pak zase vymazat.
Pro názorné předvedení si vložím na layout tlačítko a ve zdrojovém kódu udělám obsluhu události Click. Abych mohl přistupovat ke storyboardům, tak musím přidat

using System.Windows.Media.Animation;

V obsluze tlačítka si tedy najdu ten storyboard a ten aplikuju na mnou zvolené TextBlocky.

Storyboard animace = (Storyboard)FindResource("StoryboardAnimaceBackground");
animace.SetValue(Storyboard.TargetNameProperty, TB1.Name);
animace.Begin();
animace.SetValue(Storyboard.TargetNameProperty, TB4.Name);
animace.Begin();
animace.SetValue(Storyboard.TargetNameProperty, TB5.Name);
animace.Begin();


Tím je vyřešený celý problém. Udělám ještě drobnou úpravu v Xaml kódu, jelikož nechci aby mi animace vždy zůstala zastavená na konci, ale aby se ukončila. Do storyboardu v Xamlu přidám FillBehavior="Stop" a je to.


Přeji mnoho zdaru.