GenericDynamicSpxForm e WebSimplexTabs

Spesso per rendere una maschera (Form) più compatta si distribuiscono i controlli su più pannelli o View sovrapposti, selezionabili attraverso delle linguette o Tabs.

Il Framework Simplex offre una collezione di User Controls denominata WebSimplex. Tra i controlli di questa collezione vi è WebSimplexTab che implementa un gruppo di linguette (Tabs) associato ad un controllo MultiView: selezionando una linguetta è possibile portare in primo piano il corrispondente pannello-contenitore View della MultiView associata.

Interagire con un controllo ASP.NET MultiView non è facile, specialmente per quanto riguarda la lettura dei dati contenuti nei controlli della maschera che non si trovano nella View in primo piano. Se non si fa attenzione è possibile leggere dei valori null sebbene, interagendo con il controllo MultiView, tutti i suoi controlli risultino visibilmente popolati. Questo perché i controlli MultiView e View sono di tipo “server” ed i campi della View in primo piano, cioè quella visibili a video, sono gli unici effettivamente disegnati dal browser; gli altri semplicemente non esistono (in realtà vengono conservati in un’area denominata ViewState che altro non è che una stringa compressa binaria che viene passata dal browser al server nel corpo della richiesta http come valore di una coppia chiave-valore).

In molti hanno riscontrato (e risolto) questa issue (vedi gli approfondimenti in fondo all’articolo).

Questa issue si risolve abbastanza facilmente usando gli strumenti del Framework Simplex. La tecnica è questa:

  1. Immediatamente prima che venga variata la visualizzazione della View in primo piano, a seguito della selezione di un’altra linguetta (Tab), il contenuto dei suoi controlli viene copiato nell’oggetto di classe SQLTable che usiamo per la persistenza dei valori.
  2. Quando infine viene salvato nel database l’oggetto di classe SQLTable che usiamo per la persistenza dei valori, vengono copiati nell’oggetto solo quegli attributi che corrispondono ai controlli della View in primo piano, gli altri no.

Per copiare nell’oggetto SQLTable solo i valori dei controlli della View che sta per lasciare il primo piano, come indicato nel precedente punto 1, è sufficiente definire il metodo gestore dell’evento BeforeTabChange del controllo WebSimplexTabs, dichiaralo come delegato di tipo WebSimplex_BeforeTabChangeHandler e registrarlo.

Ecco fatto.

In pratica.

Se questo è il metodo, definito in una maschera derivata dalla classe GenericDynamicSpxForm, che dovrà gestire l’evento BeforeTabChange:

protected void selectionChangeOnTab(Object p_sender, EventArgs p_e)
{
        WebSimplex.WebSimplexTabs _trgt = (WebSimplex.WebSimplexTabs)p_sender;
        MultiView _mw = null;
        View _vw = null;

        if (_trgt != null)
        {
            _mw = _trgt.AssociatedMultiView;
            if (_mw != null)
            {
                _vw = _mw.Views[_mw.ActiveViewIndex];
                if (_vw != null)
                {
                    copyValues(TBL_UNDER_FORM, _vw.ID, "System.Web.UI.WebControls.View");                        
                }
            }
        }
}

in fase di caricamento (Page_Load) della maschera tale metodo gestore dovrà essere dichiarato come delegato e registrato, appunto, come gestore dell’evento BeforeTabChange.

protected override void Page_Load(object sender, EventArgs e)
{
            base.Page_Load(sender, e);
            #region DELEGATO DI GESTIONE DEI TABS
            WebSimplex.WebSimplexTabs _wst = (WebSimplex.WebSimplexTabs)R_Dynamic.FindControl("R_DynamicTABS");
            if (_wst != null)
            {
                // _wst.ChangeTab += new WebSimplex_ChangedTabHandler(this.selectionChangeOnTab);
                _wst.BeforeTabChange += new WebSimplex_BeforeTabChangeHandler(this.selectionChangeOnTab);
            }
            #endregion
// ... altro ...
}

Infine, il gestore dell’evento _Click() che salva l’oggetto TBL_UNDER_FORM di classe SQLTable dovrà eseguire quanto spiegato nel precedente punto 2.

        protected override void R_Salva_Click(object sender, EventArgs e)
        {
            //WRITE YOUR CODE FROM HERE

            #region SALVATAGGIO PRENDENDO I DATI DAI TABs
            try
            {
                MultiView _mvw = (MultiView)searchControl(R_Dynamic, "R_DynamicMultiView", "System.Web.UI.WebControls.MultiView");
                View _vw = null;
                //<added @MdN: 30/11/2020>
                if (_mvw != null)
                {
                    _vw = _mvw.Views[_mvw.ActiveViewIndex];
                    if (_vw != null)
                    {
                        this.copyValues(TBL_UNDER_FORM, _vw.ID, "System.Web.UI.WebControls.View");
                    }
                }
                //</added @MdN: 30/11/2020>

                TBL_UNDER_FORM.save(true);
            }
            catch (simplex_ORM.Spx_ORMMessage _ORMM)
            {
                // Messaggio di errore
            }
            #endregion

            Session.Add(MyName, TBL_UNDER_FORM);
           
            // Operazioni conclusive
        }

Questo è quanto.

Per approfondire sul controllo MultiView: https://docs.microsoft.com/it-it/dotnet/api/system.web.ui.webcontrols.multiview?view=netframework-4.8

Per approfondire sul controllo View: https://docs.microsoft.com/it-it/dotnet/api/system.web.ui.webcontrols.view?view=netframework-4.8

Per approfondire sulle issues del controllo MultiView: http://codeverge.com/asp.net.custom-server-controls/multiview-in-compositecontrol/91887

https://forums.asp.net/t/2056315.aspx?Howto+keep+state+in+User+Controls+in+a+MultiView

Per approfondire sulla ViewState: https://www.aspitalia.com/articoli/asp.net/viewstate.aspx

02/12/2020

Michele de Nittis

Lascia un commento