Haladó programozás (C#) 2007–2008, I. félév BMF NIK
Saját vezérlők készítése Osztályok származtatása a System.Windows.Forms névtér vezérlőiből Származtatott vezérlők felhasználása és tesztelése
Saját vezérlők származtatása a System.Windows.Forms.UserControl osztályból Vezérlőelemek hozzáadása, tulajdonságok bevezetése és módosítása Vezérlők fontosabb speciális attribútumai
Saját összetett vezérlőkre épülő alkalmazások fejlesztése Komplex funkcionalitású vezérlő fejlesztése és integrálása a Visual Studio környezetbe Saját vezérlők elhelyezése az Eszköztárban
© Miklós Árpád, BMF NIK, 2007
[email protected]
Hallgatói tájékoztató A jelen bemutatóban található adatok, tudnivalók és információk a számonkérendő anyag vázlatát képezik. Ismeretük szükséges, de nem elégséges feltétele a sikeres zárthelyinek, illetve vizsgának. Sikeres zárthelyihez, illetve vizsgához a jelen bemutató tartalmán felül a kötelező irodalomként megjelölt anyag, a gyakorlatokon szóban, illetve a táblán átadott tudnivalók ismerete, valamint a gyakorlatokon megoldott példák és az otthoni feldolgozás céljából kiadott feladatok önálló megoldásának képessége is szükséges.
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
2
1
Windows Forms vezérlők osztályhierarchiája
Saját összetett vezérlők javasolt őse A nem vizuális komponensek őse
Saját egyedi vezérlők javasolt őse
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
3
Új vezérlők származtatási lehetőségei • System.Object Az új vezérlőt teljes egészében el kell készíteni, fejlesztése rendkívül időigényes, de működése teljes mértékben meghatározható
• System.ComponentModel.Component Elsősorban nem látható (felhasználói felületet nem igénylő) komponensek esetén ajánlott (pl. időzítő, eseménynapló, soros/USB port stb.)
• System.Windows.Forms.Control Az új vezérlő automatikusan képes ablakkezelésre, számos tulajdonsága és eseménye van, ugyanakkor minden rajzolási funkcióját el kell készíteni Ez a megoldás a programok teljesítménye szempontjából optimális
• System.Windows.Forms.UserControl Az új vezérlőt már meglévő vezérlők kompozíciójaként állíthatjuk elő tetszőleges saját tulajdonságokkal és eseményekkel Ez a megoldás a fejlesztési időszükséglet szempontjából optimális
• System.Windows.Forms.* Meglévő vezérlőkre nagymértékben hasonlító vezérlők készítéséhez ajánlott V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
4
2
Feladat (1) Készítsünk olyan szövegdobozt, amely sárga háttérszínnel jelzi, ha a benne lévő szöveg nem módosítható! Ötletek: – Célszerű már meglévő vezérlőből származtatni A System.Windows.Forms.TextBox vezérlő ideális választás erre a célra.
– Ha az ősvezérlőnek már van a kívánthoz hasonló funkciót megvalósító metódusa vagy tulajdonsága, használjuk fel ReadOnly tulajdonság
– Az elkészült vezérlő példányait kézzel kell létrehozni a teszteléshez A Visual Studio eszköztárában („Toolbox”) nem jelennek meg automatikusan az új vezérlők. Az elkészült vezérlőknek az eszköztáron történő elhelyezésére később látunk példát.
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
5
Megoldás (1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
using System; using System.Drawing; using System.Windows.Forms; public class TextBoxEx: TextBox { public new bool ReadOnly { get { return base.ReadOnly; } set { if (value) this.BackColor = Color.Yellow; else this.BackColor = Color.FromKnownColor(KnownColor.Window); base.ReadOnly = value; } } }
MainForm.cs V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
6
3
Kompozícióra épülő vezérlők • Ősük a System.Windows.Forms.UserControl osztály • Elsődleges céljuk bővített funkcionalitású, egyszerűen újrafelhasználható összetett vezérlők előállítása Képességeik nem korlátozódnak az őket alkotó vezérlők képességeinek összességére, akár teljesen önálló funkcionalitással is rendelkezhetnek (például saját, alkotóelemeiktől független eseményekkel). Lehetőséget adnak emellett gyakran használt alapfunkciók beépítésére (például listák elemeinek előre feltöltése szokványos adatokkal vagy formázási és adatellenőrzési funkciók beépítése a vezérlőbe), és igen egyszerűen integrálhatók a Visual Studio fejlesztőkörnyezetbe. Legnagyobb előnyük az újrafelhasználhatóság, ami – az egységes megjelenés és funkcionalitás mellett – különösen nagyobb fejlesztéseknél fontos. Sokszor használjuk őket arra is, hogy tipikusan együtt használt vezérlőket egyetlen komponenssé egyesítsünk (például címke + szövegmező).
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
7
Feladat (2) Készítsünk újrafelhasználható címszerkesztő komponenst, amely lehetőséget ad ügyfeleink címadatainak (város, irányítószám, utca, házszám) bevitelére! Ötletek: – A vezérlőt a System.Windows.Forms.UserControl osztályból származtassuk Célszerű a Visual Studio segítségével osztálykönyvtárat („Class Library”) létrehozni, majd az „Add User Control...” funkció segítségével létrehozni a komponens alapjait. Ezt követően egy másik projektet is hozzunk létre a teszteléshez, ez azonban már Windows alkalmazás legyen. Az új vezérlő saját tulajdonságai és eseményei itt lesznek láthatók.
– Ha az új vezérlő belső elemeinek tulajdonságait vagy eseményeit kívülről láthatóvá szeretnénk tenni, ágyazzuk saját tulajdonságba vagy eseménybe A vezérlő belső alvezérlőit (pl. TextBox) semmiképpen sem ajánlatos nyilvánossá tenni.
– Az új vezérlő tervezési idejű viselkedését attribútumok segítségével elegánsan integrálhatjuk a fejlesztőkörnyezetbe (lásd később) Ezzel segítjük a komponens későbbi felhasználóit (sőt, gyakran saját magunkat is).
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
8
4
Megoldás (2)
Új tulajdonság megadása és kiegészítése attribútumokkal
AddressEditor.cs V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
9
Vezérlők attribútumai (kivonatos referencia) Attribútum neve
Attribútum leírása Tervezési idejű attribútum, amely megadja, hogy a BindableAttribute hozzárendelt tulajdonság támogat-e automatikus adatkötést Megadja, hogy a hozzárendelt tulajdonság látható-e a Visual BrowsableAttribute Studio tulajdonságszerkesztőjében („Properties Window”) A tulajdonságszerkesztő az itt megadott kategóriába fogja CategoryAttribute sorolni a hozzárendelt tulajdonságot A hozzárendelt osztály alapértelmezett eseményének DefaultEventAttribute beállítására szolgál A hozzárendelt osztály alapértelmezett tulajdonságának DefaultPropertyAttribute beállítására szolgál A hozzárendelt tulajdonság alapértelmezett értékét közli a DefaultValueAttribute Visual Studio tulajdonságszerkesztőjével A tulajdonság leírása (a tulajdonságszerkesztő alsó panelén DescriptionAttribute jelenik meg) Megadja, hogy a tulajdonság kizárólag tervezési időben DesignOnlyAttribute módosítható
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
10
5
Feladat (3) Készítsünk vezérlőt, amely lehetővé teszi hierarchikus jellegű mappastruktúrák bejárását és a bennük lévő mappák és fájlok adatainak megjelenítését! A vezérlő emellett tegye lehetővé a kiinduló mappa (gyökérelem) megadását és a vezérlő felületén kiválasztott elem (fájl vagy mappa) adatainak kiolvasását is! Ötletek: – A vezérlőt a System.Windows.Forms.TreeView osztályból származtassuk Célszerű a Visual Studio segítségével osztálykönyvtárat („Class Library”) létrehozni, ezután az „Add User Control...” funkció segítségével létrehozni egy új összetett vezérlőt, majd végül a vezérlő ősét a kódban kézzel átírni. Ezt követően egy másik projektet is hozzunk létre a teszteléshez, ez azonban már Windows alkalmazás legyen. Az új vezérlő saját tulajdonságai és eseményei itt lesznek láthatók.
– A mappák bejárását célszerű rekurzív algoritmussal megvalósítani – A mappák és a fájlok adatait érdemes magukban a megjelenített csomópontokban tárolni Ennek megvalósításához származtassunk megfelelő tárolóosztályokat a System.Windows.Forms.TreeNode osztályból. V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
11
Megoldás (3)
FolderTree.cs V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
12
6
Várható buktatók és nehézségek • Rekurzív mappabejárás – Gyakori hibalehetőség a végtelen rekurzió, amit az ilyenkor keletkező StackOverflowException kivétel jelez
• A fa gyökéreleméhez tartozó elérési út beállítása – A kiinduló mappához (pl. „C:\Windows\system32”) érdemes saját tulajdonságot készíteni (pl. „RootFolder” néven) – Probléma: mikor és hogyan olvassa be a vezérlő a kért mappa tartalmát? A vezérlők tervezési időben, a Visual Studio grafikus felületén is „élnek” és futtatják az általunk írt kód megfelelő részeit, ezért rendkívül átgondoltan kell őket megtervezni. Amikor egy vezérlőt felhelyezünk egy készülő alkalmazás ablakába, a Visual Studio meghívja a vezérlő paraméter nélküli konstruktorát, ezért ebben nem szabad olyan kódot elhelyezni, ami bizonyos hardver, külső szoftverelem vagy mappák, illetve fájlok meglétét feltételezi. A fentiek következtében nagyon fontos a kivételek megfelelő kezelése is (pl. a gyökérelem helytelen megadása, fájlelérési hibák...).
• Sok almappát és fájlt tartalmazó mappastruktúra esetén nagyon sokáig tarthat a betöltés
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
13
Saját vezérlők elhelyezése az Eszköztárban • A Visual Studio eszköztárában tetszőleges .NET vagy .COM (más néven ActiveX) komponens elhelyezhető A kívánt komponenst tartalmazó szerelvényt a „Tools” menü „Choose Toolbox Items…” menüpontjának kiválasztása után adhatjuk meg (a listán nem szereplő komponenseket a „Browse…” gombbal kereshetjük meg). A komponensekhez a ToolboxBitmapAttribute attribútum használatával saját ikon is megadható.
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
14
7
Irodalomjegyzék (alapismeretek) • Nagel, Evjen, Glynn, Skinner, Watson, Jones: Professional C# 2005 Kiadó: Wiley Publishing, Inc., 2006 ISBN: 978-0-7645-7534-1 Web: http://www.wiley.com/, http://www.wrox.com/ Nyelv: angol Terjedelem: 1540 oldal
Windows Forms vezérlők: 751–786. o. Saját komponensek és vezérlők készítése: 787–800. o.
• Microsoft Corp., Visual Studio Developer Center Windows Forms vezérlők: http://msdn2.microsoft.com/en-us/library/ettb6e2a(VS.80).aspx Saját komponensek és vezérlők készítése: http://msdn2.microsoft.com/en-us/library/ms171766(VS.80).aspx
V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
15
Kiegészítés: rekurzív algoritmusok • A rekurzív algoritmusok olyan lépéssorozatokat jelentenek, amelyek egyik lépése szintén maga az algoritmus Az algoritmus rekurzív ismétléseinek végrehajtására általában más-más paraméterekkel kerül sor. Ha a rekurzív ismétlés az algoritmus utolsó lépése, akkor végrekurzióról („tail recursion”), ha utána további feldolgozási lépések történnek, akkor bővítő rekurzióról („augmenting recursion”) beszélünk. A rekurzív algoritmusoknál kulcsfontosságú, hogy gondoskodjunk garantált kilépési feltételről, ellenkező esetben végtelen rekurziós ciklusba kerülne a program, és az operációs rendszer (vagy a keretrendszer) leállítja. Példa egyszerű bővítő rekurzív algoritmus C# nyelvű megvalósítására: 1 2 3 4 5 6 7
V1.0
int Faktoriális(int x) { if (x <= 1) return 1; else return x * Faktoriális(x-1); }
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
18
8
Kiegészítés: az ISupportInitialize interfész • Az interfészek segítségével az osztályhierachiától függetlenül írható elő funkcionalitás más (az interfészt „támogató”) osztályok számára A témáról további információk az AAO OOP előadásanyagban találhatók.
• Az ISupportInitialize interfészt támogató komponensek számára a Visual Studio garantálja, hogy az automatikusan előállított InitializeComponent() metódus belsejében a komponens első tulajdonságának beállítása előtt meghívja a BeginInit() metódust, az utolsó tulajdonság beállítása után pedig az EndInit() metódust Így elérhető, hogy a komponens értesüljön arról, amikor létrehozását követően tulajdonságait a Visual Studio beállítja a tervezéskor megadott értékekre. Ez két szempontból is hasznos: – egyrészt nem fordulhat elő, hogy (pl. összefüggő tulajdonságok esetén) menet közben a komponens időlegesen érvénytelen állapotba kerül, – másrészt elkerülhető az esetleg időigényes adat- vagy képernyőfrissítés többszöri megismétlése minden egyes tulajdonság beállítása után. V1.0
2007. szeptember 7.
© Miklós Árpád, BMF NIK, 2007
[email protected]
19
9