A mellékelt példa két részből áll: a TestControl könyvtárban található projektben készítünk egy új kontrolt, melynek egyetlen új property-éhez egy property szerkesztő ablakot is létrehozunk. A TestApp könyvtárban lévő projektben a kontrol felhasználására készült példa.
Kezdjük tehát a kontrol elkészítésével. Ennek különösebb feladata nem lesz, hiszen most a cél a property szerkesztő ablak létrehozásának bemutatása és nem egy valós kontrol készítése.
A kontrolt a UserControl1.cs-ben találjuk. Létrehozása a hagyományos módon történik.
public UserControl1()
{
InitializeComponent();
A konstruktorban megváltoztatjuk a kontrol stílusát. Ehhez a SetStyle függvényt kell meghívnunk. Első paraméterként ControlStyles felsorolt típus egyik elemét adhatjuk meg, mellyel előírjuk, hogy melyik tulajdonságot szeretnénk ki, illetve bekapcsolni. Ez utóbbit a második paraméterben megadott logikai érték szabályozza.
Ezek alapján az Opaque stílus bekapcsolásával azt érjük el, hogy a kontrol háttérterülete nem lesz törölve az adott háttérszínnel. Ennek az lesz a következménye, hogy a kontrol átlátszó lesz azokon a helyeken, ahová nem rajzolunk. Ennek akkor van haszna, ha pont ez a cél, vagy ha a kontrol teljes területét mi magunk rajzoljuk ki. Ez esetben felesleges lenne a törlés amúgy is.
SetStyle(ControlStyles.Opaque, true);
A ResizeRedraw stílus bekapcsolásával azt érjük el, hogy a kontrol méretének megváltoztatásakor automatikusan meghívásra kerül az újrarajzolásért felelős függvény.
SetStyle(ControlStyles.ResizeRedraw, true);
}
Létrehozunk egy int típusú property-t, melynek adatát az FNumber változóban tároljuk. E property-nek annyi lesz a szerepe, hogy a benne tárolt számot rajzoljuk ki a kontrol területére.
A leglényegesebb feladatot a property létrehozásakor kell elvégeznünk: itt adhatjuk meg egy attribútum formájában, hogy az adott property-hez milyen típusú property szerkesztő osztályt rendelünk hozzá. Az Editor attribútumban két paramétert használunk: az elsőben megadjuk a property szerkesztő osztály típusát, a másodikban pedig annak ősosztályát, az UITypeEditor-t.
A NumberEditorClass osztály lesz a saját osztályunk, melyet a NumberEditorClass.cs-ben hozunk létre, de előbb nézzük még a kontrol további részeit.
[
Editor(typeof(NumberEditorClass), typeof(UITypeEditor))
]
public int Number
{
get { return FNumber; }
set
{
FNumber = value;
Invalidate();
}
}
Vissza van még a kontrol rajzolatának elkészítése, melyhez létrehozzuk a kontrol Paint eseményét.
Első lépésben kifestjük a kontrol teljes hátterét egy színátmenetes ecsettel.
private void UserControl1_Paint_1(object sender, System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.FillRectangle(new LinearGradientBrush(this.ClientRectangle, Color.White, Color.Aqua, 45), this.ClientRectangle);
Rajzolunk egy keretet a kontrol köré a DrawRectangle hívásával.
e.Graphics.DrawRectangle(new Pen(Color.Blue, 1), 0, 0, Width-1, Height-1);
Végül kiírjuk a property-ben megadott számot.
e.Graphics.DrawString(FNumber.ToString(), new Font("Verdana", 10, FontStyle.Bold), new SolidBrush(Color.Black), 10, 10);
}
Nézzük most a NumberEditorClass.cs forrását, ahol elkészítjük az új property szerkesztő osztályt, melyet az UITypeEditor osztályból származtatunk.
public class NumberEditorClass: System.Drawing.Design.UITypeEditor
{
Ebben két függvény felülírására lesz szükségünk. Az egyik a GetEditStyle függvény, melyen keresztül megadhatjuk, hogy milyen típusú property szerkesztőt hozunk létre.
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
if (context != null && context.Instance != null)
{
Ezt a UITypeEditorEditStyle felsorolt típus Modal elemének választásával tehetjük meg, melynek hatására a property-nk szerkesztésekor a Properties ablakban megjelenik egy kis nyomógomb, melynek most még funkciója nem lesz.
return UITypeEditorEditStyle.Modal;
}
return base.GetEditStyle(context);
}
Ahhoz, hogy e kis gomb funkcióval is rendelkezzen, felül kell írnunk az EditValue függvényt is. Ez akkor kerül meghívásra, amikor a property értékének szerkesztése megkezdődik. Ez lesz az a pillanat, amikor a szükséges ablakot megjeleníthetjük.
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
if (context != null && context.Instance != null && provider != null)
{
Az ablak megjelenítéséhez nem árt, ha rendelkezünk eggyel. A NumberForm.cs forrásban készítünk egy Windows Form-ot, melyet az adatbevitelhez használunk. Itt most létrehozunk ebből egy példányt.
NumberForm nf = new NumberForm();
A property aktuális értékét megkapjuk a függvény value paraméterén keresztül, így ezt most átadjuk a Form számára.
nf.NumberValue = (int)value;
Ezt követően megjelenítjük az ablakot.
Az ablak bezárása után pedig kiolvassuk a Form-on megadott értéket. Ezt adjuk majd a függvény visszatérési értékének, így ezzel megváltoztatjuk a property aktuális tartalmát.
value = nf.NumberValue;
}
return value;
}
Utolsó lépésként a nézzük a NumberForm.cs-t. Ebben találunk egy alap Form-ot, melyen egy TextBox szolgál a property értékének bevitelére, valamint egy gomb a Form bezárására.
private void button1_Click(object sender, System.EventArgs e)
{
Close();
}
Szükségünk lesz még egy int típusú property-re is, melyen keresztül elérhetjük a Form-on kívülről is a TextBox aktuális értékét.
public int NumberValue
{
get { return Int32.Parse(textBox1.Text); }
set { textBox1.Text = value.ToString(); }
}
Ezzel a kontrol elkészült, lefordítása után felvehetjük azt a ToolBox-ra, ha ott jobb gombbal kattintunk és a Customize ToolBox menüpontot választjuk.
A TestApp projektben ezek után feltehetjük az imént készített kontrolt és annak Number property-jére kattintva megjelenik mellette kis nyomógomb. Ha ezt választjuk, akkor pedig meg kell jelennie a NumberForm-nak, ahol elvégezhetjük a property értékének szerkesztését.