2009-09-18 7 views
5

Sto lavorando alla creazione di un'applicazione MVP (C# Winforms). La mia versione iniziale è a Critique my simple MVP Winforms app ... Ora sto aumentando la complessità. Ho scomposto il codice per gestire due campi di testo separati in due coppie vista/presentatore. È un esempio banale, ma è elaborare i dettagli di più relatori che condividono lo stesso modello.Condivisione del modello nell'app MVP Winforms

Le mie domande sono circa il modello:

  1. sto fondamentalmente usando un evento modificato proprietà sfoggiata dal modello per la notifica di una vista che qualcosa è cambiato. E 'un buon approccio? Cosa succede se arriva al punto in cui ho 100 o 1000 proprietà? È ancora pratico a quel punto?

  2. Is Instantiating il modello in ogni presentatore con   NoteModel _model = NoteModel.Instance   l'approccio corretto? Si noti che voglio essere sicuro che tutti i relatori condividano gli stessi dati.

  3. Se v'è un approccio migliore, io sono aperto a suggerimenti ....

Il mio codice simile a questo:

NoteModel.cs

public class NoteModel : INotifyPropertyChanged 
{ 
    private static NoteModel _instance = null; 

    public static NoteModel Instance 
    { 
     get { return _instance; } 
    } 

    static NoteModel() 
    { 
     _instance = new NoteModel(); 
    } 

    private NoteModel() 
    { 
     Initialize(); 
    } 

    public string Filename { get; set; } 
    public bool IsDirty { get; set; } 
    public readonly string DefaultName = "Untitled.txt"; 

    string _sText; 
    public string TheText 
    { 
     get { return _sText; } 
     set 
     { 
      _sText = value; 
      PropertyHasChanged("TheText"); 
     } 
    } 

    string _sMoreText; 
    public string MoreText 
    { 
     get { return _sMoreText; } 
     set 
     { 
      _sMoreText = value; 
      PropertyHasChanged("MoreText"); 
     } 
    } 

    public void Initialize() 
    { 
     Filename = DefaultName; 
     TheText = String.Empty; 
     MoreText = String.Empty; 
     IsDirty = false; 
    } 

    private void PropertyHasChanged(string sPropName) 
    { 
     IsDirty = true; 

     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(sPropName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

TextEditorPresenter .cs

public class TextEditorPresenter 
{ 
    ITextEditorView _view; 
    NoteModel _model = NoteModel.Instance; 

    public TextEditorPresenter(ITextEditorView view)//, NoteModel model) 
    { 
     //_model = model; 
     _view = view; 
     _model.PropertyChanged += new PropertyChangedEventHandler(model_PropertyChanged); 
    } 

    void model_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "TheText") 
      _view.TheText = _model.TheText; 
    } 

    public void TextModified() 
    { 
     _model.TheText = _view.TheText; 
    } 

    public void ClearView() 
    { 
     _view.TheText = String.Empty; 
    } 
} 

TextEditor2Presenter.cs è essenzialmente lo stesso eccetto che funziona su _model.MoreText anziché _model.TheText.

ITextEditorView.cs

public interface ITextEditorView 
{ 
    string TheText { get; set; } 
} 

ITextEditor2View.cs

public interface ITextEditor2View 
{ 
    string MoreText { get; set; } 
} 
+0

+1 Ottima domanda. Sto avendo lo stesso nella mia mente. – Marcel

risposta

3
  1. Questo approccio è buono. Tuttavia, se stai cercando di avere centinaia (migliaia persino!) Di Proprietà, allora penso che potresti avere una classe di Dio (anti-modello). Non ci sono molte buone classi con 100 proprietà. Prendi invece in considerazione la possibilità di suddividere il tuo modello in classi più piccole. Inoltre, non è necessario avere un evento separato per ogni proprietà. Se il modello viene modificato, è possibile attivare un singolo evento (che potrebbe includere informazioni che descrivono la modifica) e le visualizzazioni possono gestirlo da lì.
  2. Eviterei di utilizzare lo schema Singleton a meno che non siate sicuri di volerlo applicare. Invece, cambiare la funzione di costruzione per tutte le viste da prendere in un'istanza del modello.
+0

1. Stavo esagerando un po ', immagino. Potrei prevedere 100 cose che voglio tracciare. Il mio pensiero sul modello sarebbe quindi quello di incapsulare e aggregare quindi sarebbe qualcosa come Model.ComplexThing1 (con 10 proprietà) e Model.ComplexThing2 (con 4 proprietà), ecc. 2. Immagino di non essere sicuro se Voglio che si applichi. Come lo so? La mia comprensione del modello è che è la fonte definitiva di informazioni memorizzate durante il runtime. Nel caso, dovrebbe esserci sempre una sola istanza del modello, giusto? –

+0

@Keith: C'è una differenza in "là ** dovrebbe ** essere sempre un'istanza del modello" e "lì ** può ** essere sempre una sola istanza del modello". Sei libero di usare un'istanza singleton (piccola "!) Semplicemente creando semplicemente una singola istanza in una fabbrica, ecc., Ma usa solo un Singleton (maiuscola"! ") Quando ** devi **. –

+0

@Johan Gerell: Come "usi solo .... quando devi": c'è qualcosa di negativo in un Singleton in questo contesto? – Marcel

1

Ricordare, in qualsiasi applicazione a livelli, è normale che il modello di dominio trascenda tutti i livelli.

  1. Così, vorrei avere il vostro presentatore passare l'istanza Nota per la vista (che senza dubbio è un controllo di qualche tipo), e poi lasciare che l'associazione dati attraverso un BindingSource prendere il sopravvento. Una volta che usi l'associazione dati, i controlli ascolteranno automaticamente l'evento PropertyChanged e si aggiorneranno di conseguenza senza bisogno di codice aggiuntivo da parte tua.La notifica basata sugli eventi è l'uso appropriato qui, indipendentemente dal numero di proprietà monitorate, poiché solo gli oggetti che si preoccupano della modifica avranno effetto (rispetto al fatto che molti oggetti agiscano inutilmente).

  2. In genere, si ottengono le istanze di entità da un livello inferiore. Ad esempio, potresti implementare un servizio che restituisce le istanze di Note. Ogni volta che chiedi il servizio per la Nota n. 3, restituisce la stessa istanza di Note creata da dati persistenti. Potresti aggiungere un altro elemento al tuo livello aziendale per integrare i tuoi presentatori: potrebbe essere chiamato un oggetto di lavoro o un controller. Tutti i relatori possono consultare la loro istanza WorkItem per ottenere l'istanza corrente di Note su cui l'utente lavorerà.

vorrei prendere in considerazione esaminando esempi di come il Composite Application Block (o CAB) utilizza questi modelli per creare applicazioni smart client. Sono tutti i modelli di progettazione e i principi OO, la cui implementazione merita lo sforzo.

1
  • Alla domanda 1: L'implementazione di INotifyPropertyChanged sembra essere una buona idea per me. Probabilmente dovresti dividere le proprietà in alcune classi.
  • Alla domanda 2: Attualmente sto utilizzando un modello Singleton per condividere il mio modello MVP con più relatori. Sono felice fino ad ora, poiché questo garantisce che in realtà c'è sempre una sola istanza del mio modello.