Tworzenie obiektowego UI w OE Development Studio cz. II

Kontynuujemy budowę aplikacji rozpoczętą w pierwszej części.

Mamy formę fCustomer; teraz zbudujemy drugą formę fOrder, która będzie zawierała browser (grid) z rekordami Order dla danego Customera.

Postępujemy analogicznie jak w poprzedniej części: do nowej formy wstawiamy źródło danych binding source, zmieniamy nazwę na np. bsOrder. Definiujemy schemat dla bsOrder.

Wstawiamy DataGridView wybierając źródło danych bsOrder.

Ponieważ browser ma pokazywać tylko rekordy Order dla zadanej wartości pola CustNum (nr klienta) trzeba przekazać z nadrzędnego okna (formy) parametr. Można to zrobić np. definiując w fOrder właściwość iCustNum.

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

Metoda refreshData będzie tutaj wyglądała nieco inaczej niż w fCustomer.

    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).
        bsOrdQuery:QUERY-PREPARE ("for each order where order.custnum = "
                                   + string(iCustNum) + " by custnum").
        bsOrdQuery:QUERY-OPEN ().
        bsOrder:handle = bsOrdQuery.
        RETURN.

    END METHOD.

Wywołanie refreshData wstawiamy do kodu programu zgodnie z sugestiami z poprzedniej części.

Na koniec dodajemy do formy przycisk btnClose z etykietą Close. Definiujemy metodę dla zdarzenia Click wstawiając jedną instrukcję:

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

    END METHOD.

Teraz przechodzimy do formy fCustomer. Wstawiamy deklarację zmiennej oOrd.

    DEF VAR oOrd AS fOrder. 

Definiujemy metodę dla zdarzenia Click przycisku btnOrders.

    
    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().	//okno niemodalne

        END.
	RETURN.

    END METHOD.

Metoda tworzy instancję obiektu fOrder (najpierw sprawdza czy obiekt nie jest już zainicjowany), następie ustawia właściwość iCustNum (czyli przekazuje parametr), otwiera zapytanie i wyświetla formę w postaci niemodalnej. Oznacza to, że użytkownik ma dostęp zarówno do formy fOrder jak i fCustomer.

Gdybyśmy chcieli uruchomić fOrder w postaci modalnej (dostęp do fCustomer będzie dopiero po zamknięciu fOrder) to zamiast instrukcji oOrd:Show() trzeba napisać: WAIT-FOR oOrd:ShowDialog().

Okno z zamówieniami otwiera się przykrywając częściowo okno z klientami. Można zdefiniować parametry okna tak aby otwierało się np. tuż obok. Aby to osiągnąć trzeba skorzystać z poniższej sztuczki Wiesława:

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

Cały tryger ma teraz następującą postać:

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().	//okno niemodalne
        //WAIT-FOR oOrd:ShowDialog().	//okno modalne
        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.

Efekt widać poniżej:

Naszą aplikację trzeba jeszcze trochę usprawnić. Ponieważ zdecydowaliśmy się na okno niemodalne, trzeba obsłużyć zmianę wyświetlanego rekordu w oknie fCustomer – powinna temu towarzyszyć zmiana wyświetlanych danych w oknie fOrder.
W widoku zdarzeń bsCust klikamy na zdarzenie PositionChanged (innym zdarzeniem, które warto wziąć pod uwagę jest CurrentChanged).

Do kodu programu zostanie wstawiona metoda obsługująca to zdarzenie. Musimy dodać do niej poniższy kod:

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.

Możecie teraz sprawdzić, że jeśli okno fOrder jest otwarte, zmiana podświetlonego rekordu w oknie fCustomer powoduje wyświetlenie zamówień dla tego rekordu.

To oczywiście nie koniec. Wkrótce pojawi się następna część.

Wiesław Kurzątkowski
Piotr Tucholski