Nejprve si ukážeme smazání záznamu. Ve formuláři fCustomer přidáme tlačítko s názvem Delete, jméno např. Del.
Poklepáním na tlačítko vytvoříme metodu Del_Click, do které vepíšeme následující kód:
DEFINE BUFFER bCust FOR Customer. DEFINE BUFFER bOrder FOR Order. DEFINE VARIABLE lDel AS LOGICAL NO-UNDO. DEFINE VARIABLE iActCustNum AS INTEGER NO-UNDO. MESSAGE "Do you want to delete this record?" SKIP bsCust:InputValue["Name"]:ToString() SKIP bsCust:InputValue["City"]:ToString() SKIP VIEW-AS ALERT-BOX QUESTION BUTTONS YES-NO UPDATE lDel. IF NOT lDel THEN RETURN. |
Nyní jsme v polovině. Můžeme si ukázat zobrazení dialogového okna s dotazem (povšimněte si, že dialogové okno se zobrazí standardním příkazem ABL MESSAGE), zatím bez smazání.
Na konec metody Del_Click (za příkaz RETURN) dopíšeme kód pro smazání řádku tabulky Customer i souvisejících záznamech v tabulce Order (formálně bychom měli pokračovat dále k OrderLine).
IF NOT lDel THEN RETURN. iActCustNum = INTEGER(bsCust:InputValue["CustNum"]:ToString()). DO TRANSACTION ON ERROR UNDO, RETURN: FOR FIRST bCust WHERE bCust.CustNum = iActCustNum: FOR EACH bOrder WHERE bOrder.CustNum = bCust.CustNum. DELETE bOrder. END. DELETE bCust. END. END. |
Aby program správně fungoval, je třeba mít na paměti, že v Data Dictionary mohou být definovány databázové triggery, které chrání před ztrátou dat. Funkčnost programu je nutné ověřit v souvislosti s těmito triggery, které je nutné případně upravit, v nejhorším případě zakázat.
Po odstranění záznamu formulář automaticky neaktualizuje data. Musíme to tedy udělat sami. Kód přidáme na konec metody Del_Click:
bsCust:MovePrevious(). |
Proměnná iPos je definována jako integer. Po vymazání řádku bude kursor umístěn na předchozím řádku.
Příklad smazání řádku je nejjednodušší, protože nevyžaduje dodatečné komponenty pro úpravu dat. Nyní přidáme tlačítka Edit a Cre (pro create) a analogickým způsobem pro ně vygenerujeme metody pro událost Click.
Obvykle mohou být stejné funkce vytvořeny různými způsoby. Můžete například využít možnosti, které nabízí přímo DataGrid, ale podle Wiesława může tento přístup způsobit neočekávané problémy a není jasně popsán. Je proto vhodnější vytvořit samostatné okno pro úpravy, které poslouží pro operace Edit i Create. Vytvoříme nový formulář fCustEdit. Protože se jedná o postup analogický tomu, který byl podrobně popsán v první části série, zde uvedeme pouze slovní popis. Při změnách se omezíme na čtyři sloupce tabulky.
Do formuláře fCustEdit vložíme pole typu TextBox: CustNum, Name, City, Country a jejich návěští.
Dále přidáme tlačítka btnOK (návěští OK), btnCancel (návěští Cancel) a nastavíme jejich předdefinované funkce:
Ve vlastnostech fCustEdit nastavíme parametr CancelButton ->
btnCancel.
Ve vlastnostech btnOK nastavíme DialogResult -> OK.
Ve formuláři fCustomer upravíme metodu Edit_Click.
METHOD PRIVATE VOID Edit_Click( INPUT sender AS System.Object, INPUT e AS System.EventArgs ): DEFINE VARIABLE oCustEdit AS fCustEdit NO-UNDO. oCustEdit = NEW fCustEdit(). WAIT-FOR oCustEdit:ShowDialog(). DELETE OBJECT oCustEdit. RETURN. |
Tlačítko Edit již funguje, ale formulář je prázdný.
K úpravě dat lze použít různé metody. My definujeme proměnné a jejich vlastnosti pro každé editované pole ve formuláři fCustEdit. Např. PName pro pole Name a analogicky i pro ostatní pole.
DEFINE PUBLIC PROPERTY pName AS CHARACTER NO-UNDO |
Takto definované proměnné musíme ve vytvořeném kódu mapovat a pole formuláře fCustEdit. Nejprve to uděláme pro událost Shown.
METHOD PRIVATE VOID fCustEdit_Shown( INPUT sender AS System.Object, INPUT e AS System.EventArgs ): ASSIGN textBoxName:TEXT = pName textBoxCity:TEXT = pCity textBoxCountry:TEXT = pCountry textBoxCustNum:TEXT = string(pCustNum). RETURN. END METHOD. |
V okně se nyní zobrazí hodnoty definovaných proměnných, které pozdějí naplníme hodnotami z tabulky Customer. Hodnota sloupce CustNum je přiřazována databázovým triggerem, proto neumožníme editaci pole CustNum ve formuláři. Nastavíme vlastnosti Enabled = False a pro lepší vzhled také BorderStyle = None.
Pro uložení dat po volbě tlačítka btnOK musíme hodnoty z formuláře zapsat zpět do proměnných.
METHOD PRIVATE VOID btnOK_Click( INPUT sender AS System.Object, INPUT e AS System.EventArgs ): ASSIGN pName = textBoxName:Text pCity = textBoxCity:Text pCountry = textBoxCountry:TEXT. RETURN. END METHOD. |
Dále musíme namapovat předávání hodnot mezi formuláři fCustomer a fCustEdit, a to oběma směry a včetně zápisu upravených dat do databáze. To uděláme v metodě Edit_Click formuláře fCustomer. Nejprve v nově vytvořené instanci objektu fCustEdit nastavíme proměnné (vlastnosti) pCustNum, pName, pCity a pCountry.
... oCustEdit:pCustNum = int(bsCust:InputValue["CustNum"]:ToString()). oCustEdit:pName = bsCust:InputValue["Name"]:ToString(). oCustEdit:pCity = bsCust:InputValue["City"]:ToString(). oCustEdit:pCountry = bsCust:InputValue["Country"]:ToString(). iActCustNum = INT(bsCust:InputValue["CustNum"]:ToString()). WAIT-FOR oCustEdit:ShowDialog(). |
Nyní se ve formuláři fCustEdit zobrazí správné hodnoty sloupců z tabulky Customer.
A nakonec doplníme do téže metody zápis upravených dat do databáze:
... DO TRANSACTION ON ERROR UNDO, RETURN: FOR FIRST bCust WHERE bCust.CustNum = iActCustNum SHARE-LOCK : ASSIGN bCust.Name = oCustEdit:pName bCust.City = oCustEdit:pCity bCust.Country = oCustEdit:pCountry. END. END. bsCust:Refresh(). ... |
Editace nám nyní funguje. Analogicky můžeme postupovat při vytváření nového řádku. Kód metody Cre_Click může vypadat např. takto.
DEFINE BUFFER bCust FOR Customer. oCustEdit = NEW fCustEdit(). WAIT-FOR oCustEdit:ShowDialog(). DO TRANSACTION ON ERROR UNDO, RETURN: CREATE bCust. ASSIGN bCust.Name = oCustEdit:pName bCust.City = oCustEdit:pCity bCust.Country = oCustEdit:pCountry. rRowid = ROWID(bCust). END. refreshData(). bsCust:HANDLE:reposition-to-rowid(rRowid). RETURN. |
Proměnná rRowid slouží k nastavení kursoru formuláře na nově vytvořený záznam.
Někomu může vadit, že v poli CustNum je zobrazena 0 (nula). V té chvíli ještě není hodnota známa, protože se přiřazuje databázovým triggerem až po vyplnění formuláře. To bychom mohli řešit tím že příkaz CREATE bCust napíšeme na začátek metody a hodnotu předámě formuláři fCustEdit, museli bychom ale složitěji vyřešit transakční zpracování.
Tím je program v zásadě hotov. Na závěr si ještě ukážeme jednu užitečnou vlastnost, a tou je volba operací Create, Edit, Delete pomocí klávesových zkratek - klávesy Insert, Return, Delete.
Ve vlastnostech formuláře fCustomer nastavíme KeyPreview = True.
Na událost KeyDown objektu dgvCustomer namapujeme metodu dataGridView1_KeyDown (Událost KeyDown v .NET nemá nic společného se "šipkou dolů", je to událost vygenerovaná okamžitě po stisknutí klávesy - bez uvolnění. Analogické události jsou KeyPress pro stisk a uvolnění a KeyUp pro uvolnění klávesy).
Kód metody v fCustomer bude vypadat takto:
A nakonec doplníme do této metody zápis upravených dat do databáze:
METHOD PRIVATE VOID dataGridView1_KeyDown( INPUT sender AS System.Object, INPUT e System.Windows.Forms.KeyEventArgs ): END METHOD. |
Cre, Edit, Del jsou názvy dříve vytvořených tlačítek.
Úplně na závěr do formuláře fCustomer ještě vložíme čítač řádků. Přidáme objekt typu label s názvem labInfo a návěštím Records. V metodě refreshData na konci přidáme kód:
A nakonec doplníme do této metody zápis upravených dat do databáze:
labInfo:TEXT = "Liczba rekordów: " + STRING(bsCust:Count). |
Při každém vyvolání této metody se zobrazí počet záznamů v tabulce Customer.
Tím jsme dokončili základní vývojový cyklus aplikace s požitím .NET v ABL. V době přípravy tohoto textu byla uvolněna verze Progress OpenEdge 12 s novými vlastnostmi, proto se se k tomuto tématu ještě vrátíme.
Poznámka: Naše příklady ukazují přímou komunikaci .NET s daty v progressovské databázi. Pokud bychom chtěli
pracovat s aplikacemi běžícími na aplikačním serveru, analogicky nakonfigurujeme "BindingSource" na definované
struktuře ProDataSet s dočasnými tabulkami.
Autoři: Michal Džmuráň volně dle Piotr Tucholski, Wiesław Kurzątkowski (Novum)