Implicazioni delle maniglie tra le forme

1

Stavo sviluppando un'applicazione WindowsForm in C #, con 2 moduli. Indipendentemente da ciò che entrambi facevano, in particolare, avevo bisogno di accedere ai valori in form2 e inviarli a form1 e viceversa. Perché ciò accada, ho trovato qualcuno parlare di sovraccarico del costruttore e ha funzionato per me come ho spiegato nel codice.

Form1:

namespace miniDldMngr
{
    public partial class Main : Form
    {
        miniDldMngr.SettingsForm settingsForm; //Instantiate settingsForm

        private void settingsToolStripButton_Click(object sender, EventArgs e)
        {
            settingsForm = new miniDldMngr.SettingsForm(this); //Create handle for Form1
            settingsForm.ShowDialog(); //Form properties were changed to act like a dialog
        }

Form2:

namespace miniDldMngr
{
    public partial class SettingsForm : Form
    {
        private Main HandleToForm1; //local variable to store handle to Form1

        public SettingsForm()
        {
            InitializeComponent();
        }

        public SettingsForm(Main frm1Handle) //overloaded constructor with handle to Form1
        {
            InitializeComponent();
            HandleToForm1 = frm1Handle;
            txtIni.Text = HandleToForm1.comboLoad.Text; //here's how i access controls on form1 for example, as long as modifiers are public
        }

Ho trovato questa risposta su Stack Overflow e l'utente codesparkle ha commentato:

It's neither scalable nor OOP-like.

Il che mi porta a credere che potrebbe non essere stata la scelta migliore per risolvere il mio problema iniziale. (S) Ha inoltre aggiunto:

One approach is to create an event in the class that knows the information which needs to be shown. The form can then register one of its methods as an event handler. Once the information becomes available, the class notifies the Form by calling that handler with an argument containing the displayable information. The beauty of this approach is that the class is decoupled (not dependent on) the implementation of Form. The MVC and MVVM design patterns are other robust ways of doing it.

Ora mi rimangono alcune domande:

  1. Quali sono le implicazioni della procedura che ho usato?
  2. Perché non si tratta di un approccio orientato agli oggetti?
  3. Quale sarebbe la migliore pratica per inviare informazioni avanti e indietro tra classi / moduli?
  4. Come andresti a creare l'evento menzionato da codesparkle?
  5. Non so nulla dei pattern di progettazione MVC o MVVM, quindi alcuni link a una spiegazione strutturata sarebbero apprezzati.

Considera che sono molto nuovo alla programmazione e non ti capirò se parli come se sapessi cosa sto facendo. Gli esempi di codice funzionano con me, dal momento che posso testarli.

    
posta Fernando Silva 28.12.2011 - 03:49
fonte

2 risposte

0

Per rispondere a ciascuna delle tue domande:

Quali sono le implicazioni della procedura che ho usato?

In questo caso, stai passando un riferimento da un oggetto genitore (il modulo principale) all'oggetto figlio (il modulo Impostazioni). Il risultato di questo è che il modulo Impostazioni deve conoscere molte cose sul modulo principale per funzionare correttamente. Alcune implicazioni non tanto desiderabili:

  1. Il modulo Impostazioni deve conoscere i nomi di tutti i controlli nel modulo principale per funzionare correttamente.
  2. Devi rendere pubbliche molte cose nel modulo principale. Rendere pubbliche le cose non è un peccato mortale da nessuna parte, tuttavia ora la tua forma principale sta pubblicizzando molte funzionalità che non ha bisogno di fare pubblicità al mondo esterno. Questo è più un problema quando il tuo progetto cresce, o se lavori con più di uno sviluppatore, che curioserà tra i membri pubblici dei tuoi oggetti per capire come lavorare con il tuo codice dall'esterno.
  3. In fondo alla strada, se per qualche motivo il modulo principale e il modulo delle impostazioni erano in due diversi assembly (file DLL), potresti avere problemi perché non puoi creare riferimenti circolari.

Perché non si tratta di un approccio orientato agli oggetti?

Bene, ciò che stai facendo è orientato agli oggetti, tuttavia poiché hai un oggetto figlio dipendente da un oggetto genitore, stai andando contro Principio di inversione delle dipendenze e causano quindi accoppiamento stretto tra oggetti.

Quando le persone su SO e altri siti parlano di come è "object oriented" qualcosa, spesso si riferiscono a SOLID , che sono i cinque principi chiave della progettazione orientata agli oggetti.

Quale sarebbe la migliore pratica per inviare informazioni avanti e indietro tra classi / moduli?

Penso che in questo caso il modo più semplice per farlo sarebbe creare proprietà nel modulo Impostazioni che rappresentano i valori che vengono modificati all'interno della finestra delle impostazioni.

Ad esempio, questo codice si trova nel modulo Impostazioni:

public string UserName
{
   get { return txtUserName.Text; }
   set { txtuserName.Text = value; }
}

E questo codice sarebbe nella tua forma principale:

private void settingsToolStripButton_Click(object sender, EventArgs e)
{
    settingsForm = new miniDldMngr.SettingsForm() { UserName = lblUserName.Text };
    settingsForm.ShowDialog(); 
    lblUserName.Text = settingsForm.UserName;
}

È un po 'più codice, ma ora sei libero di apportare tutte le modifiche che desideri al modulo principale, e la forma delle impostazioni non dovrà essere aggiornata.

Ovviamente ci sono molti altri approcci che puoi seguire, il che mi porta alle tue ultime due domande:

Come andresti a creare l'evento menzionato da codesparkle?

Creare e innalzare un evento è un altro modo per evitare un accoppiamento stretto tra due classi. Si noti come gli oggetti Windows Form, come ToolStrip, siano in grado di chiamare metodi nel codice (settingsToolStripButton_Click), anche se il codice Windows Form non è collegato al codice. Questa è la bellezza degli eventi. La mia opinione è che è eccessivo in questa situazione, dal momento che si sta visualizzando il modulo come una finestra di dialogo (in cui è possibile leggere tutti i valori dopo la chiusura della finestra di dialogo), ma tuttavia ecco un esempio:

Per prima cosa, avresti un codice come questo in ImpostazioniForm:

public string UserName
{
   get { return txtUserName.Text; }
   set { txtuserName.Text = value; }
}

public event EventHandler UserNameChanged;
protected void OnUserNameChanged(EventArgs e)
{
   if(UserNameChanged != null)
   {
       UserNameChanged(this, e);
   }
}

private void txtUserName_TextChanged(object sender, EventArgs e)
{
    OnUserNameChanged(EventArgs.Empty);
}

Quindi, avresti un codice simile a questo nel tuo MainForm:

private void settingsToolStripButton_Click(object sender, EventArgs e)
{
    settingsForm = new miniDldMngr.SettingsForm() { UserName = lblUserName.Text };
    settingsForm.ShowDialog(); 

    lblUserName.UserNameChanged += 
        (sender, args) => lblUserName.Text = settingsForm.UserName;
}

Non so nulla dei pattern di progettazione MVC o MVVM, quindi alcuni link a una spiegazione strutturata sarebbero apprezzati.

Il pattern MVVM è un pattern supportato da Microsoft, principalmente per l'utilizzo in WPF. Puoi leggere una bella descrizione qui:

link

È possibile utilizzare questo modello in Windows Form, tuttavia non lo consiglierei, poiché WPF ha già completato l'impianto idraulico di base per farlo funzionare.

Buon codice!

    
risposta data 28.12.2011 - 22:17
fonte
1

Penso che gli altri siano preoccupati per l'accoppiamento stretto.

Ad esempio, cosa visualizzerà txtIni.Text quando Form2 è stato istanziato con il costruttore predefinito?

Secondo me, dovresti risolvere questo valore nella sua proprietà con un backing store, in modo che il costruttore alternativo, che Form1 chiamerebbe, potesse impostare questa proprietà.

    
risposta data 28.12.2011 - 09:36
fonte

Leggi altre domande sui tag