17. díl - Vlastní ovládací prvky v C# .NET

C# .NET Formuláře Windows Forms Vlastní ovládací prvky v C# .NET

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V předchozích 4 lekcích jsme pracovali se základními ovládacími prvky, které nabízí sám .NET Framework. Toto počínání jsme dovršili lekcí Ovládací prvky Windows Forms počtvrté. Asi však uznáte, že nejsou všemocné a zkrátka a dobře nestačí na všechno. Dnes se v C# tutoriálu podíváme na tvorbu vlastních ovládacích prvků.

Představme si, že potřebujeme udělat progressbar, který se bude načítat odzadu. Výsledek bude vypadat asi nějak takto:

Progressbar načítaný naopak

ProgresBar bude tedy celkem obyčejný, jen se bude načítat zprava doleva.

Přidání prvku do projektu

V Solution Exploreru klikneme pravým tlačítkem myši na projekt a zvolíme Add New Item. V dialogu Add New Item vybereme šablonu User Control, ovládací prvek pojmenujeme MujProgressBar.cs.

Add New Item – User Control

Otevře se nám návrhář ovládacího prvku. Do prvku vložíme PictureBox. Celému prvku nastavíme v okně Properties vlastnosti Width na 200 a Height na 25. PicureBoxu dále nastavíme Location na 0;0, Width na 200, Height na 25 a Anchor na Top, Left, Bottom a Right, tedy všechny strany. Tímto zajistíme, že ovládací prvek bude mít rozměry 200×25 a při zvětšení se rozšíří i PictureBox, na který budeme později postup vykreslovat.

V Solution Exploreru klikneme na MujOvladaciPrvek.cs, a poté na Show Code. Přidáme vlastnosti MaxValue a Value typu int. Dále ještě vytvoříme privátní atribut MinValue, kterému nastavíme hodnotu 0. V setteru vlastností zavoláme ProgressBar_Paint(), jako první a druhý parametr předáme null. Tato metoda zatím neexistuje, později ji přidáme.

private int _value = 0;
public int Value
{
        get { return _value; }
        set { _value = value;  ProgressBar_Paint(null, null); }
}
private int minValue = 0;
private int _maxValue = 100;
public int maxValue
{
        get { return _maxValue; }
        set { _maxValue = value; ProgressBar_Paint(null, null); }
}

Dále přidáme metody Increment() a Decrement(), bez parametrů. Tyto metody i přetížíme, aby přijímaly jeden parametr - Value. V těchto metodách budeme inkrementovat (či dekrementovat) hodnotu progressbaru. Kód metod bude následující:

public void Increment(int Value)
{
        if (this.Value + Value > maxValue)
                throw new ArgumentOutOfRangeException("Hodnota překročila maximum");
        this.Value += Value;

}

public void Increment()
{
        if (this.Value + 1 > maxValue)
                throw new ArgumentOutOfRangeException("Hodnota překročila maximum");
        this.Value += Value;
}

public void Decrement(int Value)
{
        if (this.Value - Value < minValue)
                throw new ArgumentOutOfRangeException("Hodnota klesla pod minimum");
        this.Value -= Value;
}

public void Decrement()
{
        if (this.Value - 1 < minValue)
                throw new ArgumentOutOfRangeException("Hodnota klesla pod minimum");
        this.Value -= 1;
}

V každé z metod ověřujeme, jestli hodnota nepřesáhla maximum nebo minimum. Pokud ano, vyvoláme výjimku ArgumentOutOfRangeException. Pokud nová hodnota bude validní, tak ji přičteme nebo odečteme.

Nyní ještě musím progressbar překreslit, přesuneme se do okna návrháře. V okně Properties se přesuneme na události a k události Paint přiřadíme obslužnou metodu ProgressBar_Paint(). Přesuneme se do editoru kódu a do obsluhy ProgressBar_Paint() přidáme následující kód:

Graphics g = pictureBox1.CreateGraphics();
double vykreslovanaDelka = (double)this.Value * 100.0 / (double)maxValue / 100.0 * (double)this.Width;
g.Clear(Color.Green);
g.FillRectangle(Brushes.White, new Rectangle(0, 0, this.Width - int.Parse(vykreslovanaDelka.ToString()), 25));

Na prvním řádku deklarujeme grafiku PictureBoxu, na kterou budeme vykreslovat. Poté vypočítáme pomocí jednoduché trojčlenky velikost (v px), kterou musíme vykreslit, a pak ji vykreslíme od konce.

Nyní se přesuňme do formuláře. Dolů na formulář přidáme 2 tlačítka a jeden NumericUpDown. Tlačítkům dodáme text + a -, numericUpDown měnit nebudeme.

Tlačítka pro inkrementaci a dekrementaci

Implementace prvku

Z Toolboxu

Všimněte si, že v okně Toolboxu přibyla nová skupina <nazev projektu> Components. V této skupině se nachází pointer, který se automaticky přidává do každé skupiny a náš progressbar. S tímto progressbarem můžeme nyní zacházet jako s každým jiným ovládacím prvkem. Přetáhněme si nový progressBar do formuláře. Nyní se v našem formuláři nachází nový ovládací prvek.

Z kódu

Přesuňme se do kódu a ve formuláři si vytvořme privátní atribut prog typu MujProgressBar a hned jej inicializujeme. V konstruktoru mu nastavíme Location na 12;43 a přidáme jej do formuláře.

MujProgressBar prog = new MujProgressBar();
public Form1()
{
        InitializeComponent();
        prog.Location = new Point(12, 43);
        Controls.Add(prog);
}

Ještě přidáme obsluhy události pro obě tlačítka, která nám budou inkrementovat a dekrementovat progressbar.

private void button1_Click(object sender, EventArgs e)
{
        try
        {
                if (numericUpDown1.Value > 1) {
                        prog.Increment(int.Parse(numericUpDown1.Value.ToString()));
                        mujProgressBar1.Increment(int.Parse(numericUpDown1.Value.ToString()));
                } else {
                        prog.Increment();
                        mujProgressBar1.Increment();
                }
        }
        catch (ArgumentOutOfRangeException ex)
        {
                MessageBox.Show(ex.Message);
        }

}

private void button2_Click(object sender, EventArgs e)
{
        try
        {
                if (numericUpDown1.Value > 1)
                {
                        prog.Decrement(int.Parse(numericUpDown1.Value.ToString()));
                        mujProgressBar1.Decrement(int.Parse(numericUpDown1.Value.ToString()));
                }
                else
                {
                        prog.Decrement();
                        mujProgressBar1.Decrement();
                }
        }
        catch (ArgumentOutOfRangeException ex)
        {
                MessageBox.Show(ex.Message);
        }
}

Program si vyzkoušejte, že funguje a progressbar se opravdu načítá odzadu.

Vlastní uživatelské prvky se hodí pro specifické věci, vytvářet si vlastní TextBox je asi nesmysl. Bylo by to to samé jako vynalézat znovu kolo. Ale pokud opravdu potřebujete nějaký prvek pro specifický účel, je to určitě správná volba.

V této lekci jste se naučili vytvářet vlastní ovládací prvky a naučili jste se je implementovat do programu. Také jste tím završili kurz Winforms a můžete pokračovat dalšími kurzy v předmětu C# .NET.


 

Stáhnout

Staženo 389x (92.41 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Jak se ti líbí článek?
8 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity (3)

 

 

Komentáře
Zobrazit starší komentáře (6)

Avatar
Michal Žůrek (misaz):4.9.2013 21:51

přesně tak proto má článek podkapitoly
Implementace prvky

  • z toolboxu
  • z kódu

první varianta je deklarována kdesi v hlubinách kam se většina z nás nikdy nedostane (ve WPF už vůbec ne). A druhá tam taky asi někde je, protože mi to fungovalo.

Nicméně ukončíme debaty. Asi jste stejně všichni pochopili že to mělo jen demonstrovat základy.

Odpovědět 4.9.2013 21:51
Nesnáším {}, proto se jim vyhýbám.
Avatar
Jirka
Člen
Avatar
Jirka:4.9.2013 21:53

Jo aha, já jsem postup s Toolboxem ignoroval, protože se mi ze záhadných důvodů komponenta vůbec neobjevila, tak jsem rovnou přešel na postup pomocí kódu.
Vůbec jsem si nevšiml toho druhého progress baru. Tak hlavně, že jsme se domluvili :)

 
Odpovědět 4.9.2013 21:53
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Jirka
Jan Vargovský:4.9.2013 21:56

Když vytvoříš komponentu, musíš potom kód zkompilovat (Debug -> build nebo F6) aby se ti objevil v designeru.

 
Odpovědět 4.9.2013 21:56
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Zdeněk Pavlátka:10.10.2014 15:11

V článku je několik chyb:

1. prvek na začátku pojmenuješ MujProgressBar.cs a po chvíli tam máš

V Solution Exploreru klikněte na MujOvladaciPrvek.cs, a potom klikněte na Show Code.

2. V kódu metody Increment() máš trochu nesmysl:

public void Increment()
{
        if (this.Value + 1 > maxValue)
                throw new ArgumentOutOfRangeException("Hodnota překročila maximum");
        this.Value += Value; // tím hodnotu zdvojnásobíš, máš přičíst jedničku
}
Odpovědět  +1 10.10.2014 15:11
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Zdeněk Pavlátka
Jan Vargovský:10.10.2014 17:26

Mezi námi, ta metoda Increment bez parametru (ofc i Decrement) je úplně zbytečná.

viz

public void Increment(int Value)
{
        if (this.Value + Value > maxValue)
                throw new ArgumentOutOfRangeException("Hodnota překročila maximum");
        this.Value += Value;

}

public void Increment()
{
        Increment(1);
}
Editováno 10.10.2014 17:27
 
Odpovědět  +2 10.10.2014 17:26
Avatar
Marek Leopold:6.3.2015 3:01

Ahojte,
Tvořím aplikaci, ve které jsem využil vytvoření prvku.
Vložil jsem ho do aplikace, dal mu jméno (prvek.Name = "jmeno"), ale když zkusím jmeno.Hide() tak mi to nefunguje, jak bych měl tedy skrýt mnou vytvořený prvek, který vkládám v kódu, nikoli v designeru ?
Díky

 
Odpovědět 6.3.2015 3:01
Avatar
Odpovídá na Marek Leopold
Michal Žůrek (misaz):6.3.2015 6:11

Zkus přes vlastnost Visiblity.

Odpovědět 6.3.2015 6:11
Nesnáším {}, proto se jim vyhýbám.
Avatar
Marek Leopold:6.3.2015 7:26

Děkuji za radu, ale bohužel nefunguje.
Prvek tvořím takto:

Klavesnice kl = null;

private void .... {
Klavesnice kl = new Klavesnice(this);
            kl.Location = new Point((System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - 624), (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - 604));
            Controls.Add(kl);
            kl.Name = "Klavesnic";
            kl.BringToFront(); }

624x602 je velikost, jenom pro upřesnění

... respektive funguje, ale když to zkusím zavolat z jiné části programu, tak mi vždy spadne program

Editováno 6.3.2015 7:29
 
Odpovědět 6.3.2015 7:26
Avatar
Marek Leopold:6.3.2015 7:37

Já bych teoreticky mohl vložit tento prvek i přes designer, ale neobjevil se mi v toolboxu.
Měl by to být ten "Klávesnice"

 
Odpovědět 6.3.2015 7:37
Avatar
Odpovídá na Marek Leopold
Michal Žůrek (misaz):6.3.2015 7:46

Restartuj Visuak Studio, pak se tam určitě objeví.

Odpovědět 6.3.2015 7:46
Nesnáším {}, proto se jim vyhýbám.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 16. Zobrazit vše