ContentControl, Button a TextBlock

9. díl - ContentControl, Button a TextBlock

Tomáš Jecha, MVP, MCSD       10.04.2012       C#, VB.NET, WPF, Komponenty, .NET       17797 zobrazení

Článěk se věnuje základům důležité komponenty ContentControl a dvěma vizuálním komponentám: Button (tlačítko) a TextBlock (textový blok).

ContentControl

Abstraktní třída ContentControl je základem pro mnohé z komponent, které budu popisovat. Jejím hlavním účelem je dokázat nést uvnitř sebe jinou komponentu. Obsah definuje vlastnost Content (která je zároveň označená jako ContentProperty – více v tomto díle) a je typu object. Díku tomu nejsme omezeni jen na vkládání jiných komponent (UIElement), ale lze do této vlastnosti  nastavit i jiné datové typy (nejběžněji to bývá textová hodnota).

WPF se podle typu rozhodne, zda se jedná o komponentu (pokud dědí z UIElement) a nebo, zda bude potřebovat komponentu z obsahu vytvořit, jako je tomu například u textového řetězce. V tom případě se vytvoří automaticky komponenta pro zobrazování textu TextBlock (kterou popisuji dále) a hodnotu pomocí ní v textové podobě zobrazí. To výrazně zvyšuje pohodlnost vývoje, protože můžeme vkládat buď přímo textový řetězec nebo, pokud potřebujeme, lze místo něj vložit jako obsah i běžnou komponentu (potomek UIElement).

První z probíraných komponent dědících z ContentControl je tlačítko Button.

Button

Tlačítko Button jsem používal v předchozích článcích jako jednoduchou ukázkovou komponentu. Slouží jako bázový vstupní element od uživatele a nabízí řadu nastavení. Jeho hlavní úkol je naprosto zřejmý – po kliknutí má vyvolat nějakou událost, která vykoná připojený kód.

Tlačítko dědí z třídy ButtonBase, která zajišťuje základní rozhraní pro vytváření různých grafických komponent. ButtonBase následně dědí z již popsaného ContentControl.

Vzhled a obsah

Na rozdíl od starší technologie Windows Forms nabízí možnost plně modifikovat svůj vzhled (stejně jako všechny komponenty ve WPF), což je velmi užitečné. Při psaní běžné aplikace sice pravděpodobně nebudete měnit vzhled tlačítek, nicméně ta možnost tu je a nejednou jsem narazil na potřebu ji využít.

Grafická otevřenost nabízí ale i běžně použitelnější výhody. Protože tlačítko vychází z ContentControl, jeho obsah může být text a nebo libovolná další komponenta. Snadno lze tak například vytvořit tlačítko, kde je vedle popisku i obrázek:

Button with image

<Button HorizontalAlignment="Center" VerticalAlignment="Center" Padding="10">
    <StackPanel Orientation="Horizontal">
        <Image Source="http://cs.wikipedia.org/favicon.ico" Margin="0 0 5 0" Stretch="None" />
        <TextBlock Text="Wikipedia" VerticalAlignment="Center" />
    </StackPanel>
</Button>

V kódu jsem použil StackPanel z minulého dílu, který mi zajistí horizontální skládání komponent vedle sebe. Vlevo jsem vložit obrázek (budu se mu věnovat v dalších dílech) a vedle něj textový popisek. U obrázku jsem navíc nastavil odsazení pravé strany, aby nebyl nalepený na text.

Událost kliknutí

Událost reagující na kliknutí se jmenuje Click. Sice patří k jedné z mnoha událostí, kterou dokáže tento prvek vyvolat, jednoznačně je však tou nejpoužívanější.

Pro přichycení na událost můžeme použít z návrháře 2 způsoby. Prvním je zapsání názvu události stejným způsobem, jako je to u vlastností. Editor XAML kódu nám v takovém případě nabídne k navázání na existující handlery (procedura obsluhující událost) nebo vytvoření handleru nového:

Handler XAML

Druhou možností je tlačítko vybrat a v panelu vlastností přepnout na seznam událostí (ikonka blesku) a následně si požadovanou vlastnost vybrat a poklepat na ni:

WPF events

V obou případech bude výsledek stejný, v XAML kódu se vytvoří záznam s odkazem na jméno handleru a v kódu se před vytvoří metoda, která událost obsluhuje:

<Button Click="Button_Click_1"  />
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            // obsluha události
        }
    }
}

Další obecné vlastnosti

Při vývoji se může často hodit bitová vlastnost IsEnabled určující, zda je možné ovládací prvek používat. Pokud ji změníte z defaultního nastavení na hodnotu “False”, tlačítko se zneplatní a nebude jej možné stisknout.

Dále doporučuji vyzkoušet vlastnosti nastavení písma, především FontSize, FontFamily, FontStyle a FontWeight. A samozřejmě nastavení barvy pozadí Background a textu Foreground.

TextBlock

TextBlock je nejzákladnější komponenta pro zobrazování textu (neplést s TextBox sloužícím naopak pro textový vstup od uživatele). Automaticky ji využívá WPF, pokud potřebuje reprezentovat nějaký řetězec uvnitř ContentControl. Následuje jednoduchý příklad použití:

<TextBlock Text="Toto je TextBlock." />

Ekvivalentní zápis lze provést i takto:

<TextBlock>Toto je TextBlock.</TextBlock>

TextBlock ale zvládá i složitější úkoly, než je jen homogenní text. Dovnitř totiž lze vkládat dokumentové inlines. Což je typ objektu reprezentující část dokumentu. Může to být tok textu (třída Run), formátování (třída Bold, Italic…) nebo řada dalších speciálních elementů. Pokročilejším dokumentům (odstavce, pokročilé formátování atp.) se budu věnovat samostatným dílem. V následujících řádcích proberu pouze základní typy:

  • Run – může obsahovat textový řetězec
  • LineBreak – vkládá odřádkování
  • Bold – tučné písmo
  • Italic – kurzíva
  • Underline – podtržené písmo

Použití těchto typu inlines:

<TextBlock>
    <Run Text="Toto je " /><!-- obyčejný text -->
    <Bold><Run Text="TextBlock" /></Bold><!-- tučný text -->
    <LineBreak /><!-- odřádkování -->
    <Italic><Run Text="Další řádek." /></Italic><!-- italic -->
</TextBlock>

WPF TextBlock

Uvedený zápis je možné i zjednodušit a vynechat elementy “Run”. Ty se totiž použijí automaticky, pokud zapíšeme jako obsah textový řetězec:

<TextBlock>
    Toto je <!-- obyčejný text -->
    <Bold>TextBlock</Bold><!-- tučný text -->
    <LineBreak /><!-- odřádkování -->
    <Italic>Další řádek.</Italic><!-- kurzíva -->
</TextBlock>

Velikost a typ písma můžete stejně jako u ostatních ovládacích prvků (například Button) nastavovat přímo na samotném elementu. Navíc v případě TextBlock lze tyto vlastnosti měnit i na konkrétních inline objektech. Příklad ukazuje změnu velikosti (FontSize) a typu písma (FontFamily) na celém TextBlock objektu i jednom z inline bloků Bold:

<TextBlock FontSize="20" FontFamily="Comic Sans MS">
    Toto je <Bold FontSize="50" FontFamily="Consolas">TextBlock</Bold>
</TextBlock>

WPF TextBlock - inlines

Na inline objektech existuje i několik dalších doplňujících vlastností. Nejzákladnější jsou tyto:

  • Foreground – barva textu (lze nastavit na inline objektu i celém elementu TextBlock)
  • Background– barva pozadí (lze nastavit na inline objektu i celém elementu TextBlock)
  • BaselineAligment – zarovnání inline objektu proti ostatním inlines (následující ukázka demonstruje zarovnání menší textu na střed výšky většího textu).

Ukázka použití:

<TextBlock FontSize="20" FontFamily="Comic Sans MS">
    <Run Text="Toto je " BaselineAlignment="Center" Background="Yellow" />
    <Bold Foreground="Green" FontSize="50" FontFamily="Consolas">TextBlock</Bold>
</TextBlock>

WPF TextBlock - properties

TextBlock tedy lze využít jako jednoduchý textový popisek i pro složitější reprezentaci formátovaného textu.

Poznámka: Ve WindowsForms se využíval jako textový popisek objekt Label. Ten ve WPF existuje také, ale využívá se v případech, kdy chceme vytvořit popisek ke konkrétnímu ovládacímu prvku a chceme dovolit používání přístupových klávesových zkratek. Tomu se budu věnovat v samostatném díle.

Závěr

Rozepisovat jednotlivé vlastnosti a možnosti nastavení uvedených prvků by bylo zbytečné. Proto se v těchto článcích soustředím spíše na základní funkčnost nebo konkrétní postupy. Doporučuji se však na seznam vlastností a událostí prvků podívat, vyzkoušet a v případě nejasností napsat do diskuze pod některý z mých článků.

 

hodnocení článku

4 bodů / 4 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Všechny díly tohoto seriálu

10. Návrh přihlašovacího formuláře - TextBox, PasswordBox, CheckBox a Label 20.04.2012
9. ContentControl, Button a TextBlock 10.04.2012
8. Canvas, StackPanel, WrapPanel 22.03.2012
7. Grid 16.03.2012
6. Základy pozicování 23.02.2012
5. Device independent pixels 16.02.2012
4. Architektura a objektový model WPF 09.02.2012
3. Jazyk XAML 02.02.2012
2. Architektura WPF – Dispatcher 26.01.2012
1. Úvod do Windows Presentation Foundation (WPF) 19.01.2012

 

 

 

Nový příspěvek

 

Diskuse: Vestavěné komponenty 1

Zdravim,

chcel by som docielit, aby sa moj TextBox objekt spraval podobne ako sa sprava textove pole pre vkladanie URL v prehliadaci. Tj. ak pole nema "focus" a kliknem nan, chcem aby sa oznacil cely text, ktory sa v nom aktualne nachadza. Mozno je riesenie primitivne, ale nemozem prist na to, ktore udalosti sa kedy vyvolavaju. Raz mi text oznaci, raz mi len preblikne a ihned sa odznaci...

Dakujem.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V události GotFocus zavoláte na prvek TextBox metodu SelectAll().

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Takto jednoducho mi to bohuzial nefunguje. Mam dojem, ze text sa oznaci ale nasledne je zavolany kod, ktory umiestni kurzor na kliknute miesto a tym text zase odznaci. (Ale mozno sa mylim.)

Podarilo sa mi to spravit vytvorenim novej triedy MyTextBox, ktora dedila po Controls.TextBox

Public Class MyTextBox
    Inherits Controls.TextBox

    Public selected As Boolean = False

    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Input.MouseButtonEventArgs)
        MyBase.OnMouseUp(e)

        If Not Me.selected Then
            Me.selected = True
            Me.SelectAll()
        End If
    End Sub
End Class

+ do hlavneho okna som pridal nasledovny kod:

Private Sub Canvas1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Canvas1.Loaded
        AddHandler myText.LostFocus, AddressOf TextBox_LostFocus
    End Sub

    Private Sub TextBox_LostFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        myText.selected = False
    End Sub

chcel som sa vsak len spytat na jednoduchsiu cestu, pri ktorej by som pracoval priamo s Controls.TextBox.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zde je to velmi hezky popsané: http://stackoverflow.com/questions/66055...

Jak sám píšete, není to tak jednoduché, pokud se používá myš, která navíc vyvolá událost vybrání konkrétního místa v textu a to až po uvolnění tlačítka myši.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Vestavěné komponenty 1

Jenom malé doplnění,

pokud potřebujeme objekty jako Run, LineBreak, Bold, Italic, atd do componenty TextBlock nastavit programově (tj. né v XAML), musíme obsah nastavit vlastností Inline (TextBlock nemá vlastnost Content).

Vlastnost Inline je typu System.Windows.Documents.InlineCollection a jedná se o kolekci objektů System.Windows.Documents.Inline (z té Run, LineBreak, Bold, Italic dědí).

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Ano, existují vlastně dva způsoby:

1) Vložit obsah jako neformátovaný text do vlastnosti Text.

2) Vložit inline objekty do vlastnosti Inlines.

Ačkoliv ta první varianta neudělá nic jiného, než že vloží do Inlines jeden objekt typu Run, jemuž nastaví vlastnost Text na odpovídající hodnotu.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback