2012-01-07 14 views
6

WPF può essere irritante a volte.Qual è il modo migliore per condividere i dati tra una finestra WPF e i suoi controlli utente?

Ho un'applicazione abbastanza semplice che consiste in una singola finestra principale che contiene un controllo struttura a schede e diverse schede. Non mi piaceva l'idea di avere il codice per tutte le schede nello stesso file, quindi ho usato la risposta da this question per scomporre ogni scheda in un controllo utente separato.

Nella mia finestra principale ho un'istanza di un oggetto che contiene le impostazioni dell'applicazione e alcuni altri dati a livello di applicazione. Molte delle mie schede richiedono l'accesso a questi dati per scopi di associazione dei dati. Non sono stato in grado di trovare un buon modo per realizzare questo.

Prima ho provato ad accedere alla finestra padre nei controlli evento Loaded e ottenere un riferimento alla proprietà nella finestra principale che ha esposto l'oggetto impostazioni, come mostrato nel codice sottostante. Questo tipo di operazioni, ad eccezione dell'evento Loaded, viene attivato ogni volta che la scheda viene messa a fuoco. Inoltre, questo evento si verifica in ritardo nel ciclo di vita del controllo, quindi non sono in grado di eseguire il binding a nessuna delle proprietà in questo oggetto nel controllo utente XAML.

private void MyUserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    this.ApplicationSettings = ((MainWindow)Window.GetWindow(this)).ApplicationSettings; 
} 

Poi ho sperimentato con il passaggio dei dati nel costruttore di controlli utente, ma non c'è modo di farlo in XAML.

Dato che si tratta di impostazioni a livello di applicazione, è possibile rendere la classe ApplicationSettings singleton e farne riferimento ovunque, ma preferirei non farlo per scopi di testing unitario.

Quindi come si realizza qualcosa del genere? Il mio approccio è fondamentalmente sbagliato? Nella mia mente tutti questi elementi dell'interfaccia utente fanno parte della stessa finestra e pertanto dovrebbero essere in grado di accedere ai dati dalla finestra principale, ma il modello a oggetti non sembra consentirlo.

risposta

2

Si potrebbe mettere le impostazioni oggetto in una proprietà statica in una classe wrapper (SettingsHolder in questo esempio e fare riferimento a esso l'applicazione larga via

in XAML:

{Binding SettingName, Source={x:Static local:SettingsHolder.Settings}} 

con local essere lo spazio dei nomi tuo SettingsHolder classe è in

in Codice:.

var x = SettingsHolder.Settings.SettingName; 
SettingsHolder.Settings.SettingName = x; 
+0

Penso che questa sia la strada che prenderò. Come ho detto nel post originale, voglio un comportamento singleton senza il singolo singleton, e questo mi dà questo. In realtà, probabilmente renderò la classe singleton, ma lascerò il costruttore a scopi di test. Grazie! – EricTheRed

1

Nella dichiarazione del controllo utente è sufficiente impostare il contesto dei dati sull'istanza dell'oggetto che contiene tutte le cose a cui è necessario associare!

<someNamespace:EricsUserControl DataContext="{Binding InstanceOfBindingObject}"/>

Quindi è possibile accedere alle proprietà di oggetti che esempio sotto il controllo dell'utente come si farebbe normalmente.

+0

Questo è davvero buono a sapersi, e potrei usarlo per alcune altre cose, ma vorrei lasciare aperta l'opzione per accedere anche alle impostazioni nel codice. – EricTheRed

+0

@EricTheRed perfettamente sensato, ma solo un testa a testa, è possibile accedere a DataContext per un controllo utente all'interno del codice pure. Quindi, se ci si è collegati all'oggetto istanza come sopra e quindi all'interno del file code-behind è stato eseguito un po 'di 'var myInstance = (BindingObjectClass) this.DataContext', si potrebbe essere in grado di accedere a tale oggetto dalla variabile myInstance! Spero che ti aiuti in futuro! – Kevek

0

Quello che faccio è utilizzare un Frame nel Tab e inserire un Page nel Frame. (ma penso che lo stesso si possa applicare con un controllo utente). Il costruttore si attiva solo quando viene creata la pagina e puoi controllare quando viene creata la pagina e puoi passare le informazioni nel costruttore. Una pagina ha più eventi sul ciclo di vita da legare. Io uso anche l'evento Loaded per costruire l'interfaccia utente (si attiva solo una volta). Se si associa la pagina in XAML, si attiva quando si avvia l'app e non è possibile passare le informazioni. Questo sta creando una pagina e mostrandola in una finestra di dialogo, ma quella pagina potrebbe essere associata a una cornice.

 NavigationWindow winSearchXML; 
     using (new WaitCursor()) 
     { 
      winSearchXML = new NavigationWindow(); 
      winSearchXML.Content = new PageSearchResultsXML(GabeLib.GetSearchXML(GabeLib.enumXMLtype.Flat)); 
     } 
     winSearchXML.ShowDialog(); 

Devo essere onesto che alcune volte ho un ciclo di vita su una pagina che non capisco. Quindi prendi questo con un granello di sale. Ma il punto è che hai il contructor e gli eventi caricati che potrebbero darti quello che ti serve.

+0

È intelligente! Non ho mai pensato di fare qualcosa del genere. Penso che per quello a cui sto lavorando è un po 'eccessivo. Grazie comunque per l'idea. – EricTheRed

Problemi correlati