V první části článku jsme si ukázali, jak je možné pomocí nástroje  OpenEdge Developer Studio vytvořit jednoduchý .NET formulář zobrazující data z progressovské databáze. V tomto článku pokročíme dále. Nejprve vytvoříme další .NET formulář zobrazující data z tabulky Order , a poté si ukážeme vytvoření vazby Master-Detail mezi těmito formuláři.

Analogickým způsobem, jakým jsme v první části článku vytvořili formulář fCustomer, vytvoříme formulář fOrder. Datový zdroj (ProBindingSource) nyní nazveme bsOrder a propojíme jej s tabulkou Order. Poté vytvoříme prohlížeč (DataGridView) fOrder výběrem zdroje dat bsOrder. Výsledkem bude tento zatím prázdný formulář:

Image

Analogicky jako v prvním článku vytvoříme metodu refreshData, která zajistí, aby formulář zobrazoval všechna data tabulky Order

Nyní propojíme formuláře fCustomer a fOrder. Chceme ovšem také zachovat původní chování formuláře fOrder, tedy zobrazení všech dat tabulky.

Nejprve definujeme vlastnost (Property) formuláře fOrder. Důležitá je implicitní hodnota ? (neznámá hodnota).

    DEFINE PUBLIC PROPERTY iCustNum AS INTEGER NO-UNDO INIT ?
    GET.
    SET.

Metodu refreshData trochu pozměníme:

METHOD PUBLIC VOID refreshData(  ):

def var bsOrdQuery as handle no-undo.
def var bsOrdString as char no-undo.
create query bsOrdQuery.
bsOrdQuery:ADD-BUFFER (buffer order:handle).
if iCustNum = ? then bsOrdQuery:QUERY-PREPARE ("for each order").
else bsOrdQuery:QUERY-PREPARE ("for each order where order.custnum = "
+ string(iCustNum) + " by custnum").
bsOrdQuery:QUERY-OPEN (). bsOrder:handle = bsOrdQuery.

RETURN.

END METHOD.

Volání metody refreshData vložíme do kódu třídy fOrder programu jedním ze způsobů ukázaných v předchozí části. Povšimněte si, že vhodným nastavením vlastnosti iCustNum změníme chování třídy tak, jak bylo požadováno.

Nakonec vložíme do fromuláře tlačítko "Close" a definujeme metodu, která bude při jeho stisknutí aktivována.

METHOD PRIVATE VOID btnClose_Click( INPUT sender AS System.Object, INPUT e AS System.EventArgs ):
THIS-OBJECT:Close( ).
RETURN.
END METHOD.

Nyní se vrátíme k dříve vytvořené třídě fCustomer. Definujeme proměnnou typu "třída". Mějte prosím na paměti, že při kompilaci zdrojového kódu fCustomer musí být třída fOrder dostupná na PROPATH. V tomto jednoduchém příkladě používáme "strong names convention".

DEF VAR oOrd AS fOrder. 

Dále definujeme metodu, která bude spuštěna při stisknutí tlačítka Orders ve formuláři fCustomer.

    METHOD PRIVATE VOID btnOrders_Click( INPUT sender AS System.Object, INPUT e AS System.EventArgs ):
        IF (NOT VALID-OBJECT(oOrd) OR oOrd:IsDisposed) THEN DO:
            oOrd = NEW fOrder().
            oOrd:iCustNum = bsCust:InputValue["CustNum"].
            oOrd:RefreshData().
            oOrd:Show().        /* nemodální okno */

        END.
        RETURN.

    END METHOD.

Metoda nejprve zkontroluje, zda již neexistuje instance objektu fOrder a případně ji vytvoří. Poté nastaví vlastnost iCustNum podle vybraného řádku formuláře iCustomer, otevře dotaz a zobrazí formulář v nemodálním formuláři (uživatel má přístup k formulářům fOrder i fCustomer.

Image

Pokud bychom chtěli otevřít formulář fOrder jako modální, místo příkazu oOrd:Show() bychom napsali WAIT-FOR oOrd:ShowDialog(). V takovém případě by po zobrazení formuláře fOrder nebyl formulář fCustomer dostupný, dokud by formulář fOrder nebyl uzavřen.

Vhodným nastavením parametrů okna můžeme docílit toho, aby se formuláře navzájem nepřekrývaly. Například tímto kódem docílíme toho, aby se formulář fOrder otevřel vpravo od formuláře fCustomer).

oOrd:Location = new System.Drawing.Point(int(this-object:Location:X) + 
this-object:Width,int(this-object:Location:Y)).
oOrd:Height = this-object:Height.

Kód musíme samozřejmě vložit do metody btnOrders_Click, která bude vypadat takto.

METHOD PRIVATE VOID btnOrders_Click( INPUT sender AS System.Object, INPUT e AS System.EventArgs ):

IF (NOT VALID-OBJECT(oOrd) OR oOrd:IsDisposed) THEN DO:
oOrd = NEW fOrder().
oOrd:iCustNum = bsCust:InputValue["CustNum"].
oOrd:RefreshData().
oOrd:Show(). /* nemodální okno */
oOrd:Location = new System.Drawing.Point(int(this-object:Location:X) +
this-object:Width,int(this-object:Location:Y)).
oOrd:Height = this-object:Height.

END.

RETURN.
END METHOD.

A výsledek bude vypadat takto:

Image

Naše jednoduchá aplikace ale ještě není úplná. Při změně vybraného řádku ve formuláři fCustomer musí být změněn i obsah formuláře fOrder

Nejprve v seznamu událostí formuláře fCustomer vybereme událost PositionChanged a spojíme jí s metodou bsCust_PositionChanged.

Image

Poté tuto metodu přidáme do třídy fCustomer.

METHOD PRIVATE VOID bsCust_PositionChanged( INPUT sender AS System.Object, INPUT e AS System.EventArgs ):

IF VALID-OBJECT(oOrd) THEN DO:
IF oOrd:IsDisposed THEN RETURN.
oOrd:iCustNum = bscust:InputValue["CustNum"].
oOrd:RefreshData().
END.

RETURN.
END METHOD.

 

Nyní se můžete přesvědčit, že změnou vybraného řádku ve formuláři fCustomer se změní i obsah formuláře fOrder.

To je pro dnešek vše. V příštím díle si ukážeme některé parametry a metody, kterými lze měnit vzhled a chování formulářů.

Autoři: Michal Džmuráň volně dle Piotr Tucholski, Wiesław Kurzątkowski (Novum)


Nahoru