2013-06-05 7 views
9

Sto tentando di associare un Titolo finestra al ViewModel che ha una proprietà Title. Di seguito è riportato il MainWindow XAML:WPF Bind Window Title to ViewModel Property

<Window x:Class="MyProject.View.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel" 
     Title="{Binding Path=Title}" Height="350" Width="525" DataContext="{Binding Source={StaticResource mainWindowViewModel}}"> 
    <Window.Resources> 
     <vm:MainWindow x:Key="mainWindowViewModel"/> 
    </Window.Resources> 

... 

</Window> 

Quando provo ad eseguire questo, ottengo il seguente eccezione "Fornire valore 'System.Windows.StaticResourceExtension' ha generato un'eccezione Il numero di riga e la posizione del punto alla proprietà DataContext. e l'eccezione interna indica "Impossibile trovare la risorsa denominata mainWindowViewModel.

Di seguito si riporta il codice per il Model View:

namespace MyProject.ViewModel 
{ 
    public class MainWindow : INotifyPropertyChanged 
    { 
     #region Fields 

     private const string TitlebarPrefixString = "My Project"; 
     private string title = TitlebarPrefixString; 

     public string Title { 
      get 
      { 
       return this.title; 
      } // End getter 
      set 
      {  
       this.title = value; 
       OnPropertyChanged("Title"); 
      } // End setter 
     } // End property 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } // End if 
     } // End method 


     public event PropertyChangedEventHandler PropertyChanged; 

    } // End class 
} // End namespace 

La mia teoria è che le risorse vengono caricate dopo il tentativo di legare il titolo alla proprietà. Quando viene generata l'eccezione, la proprietà Resources per la finestra è vuota.

È l'unica soluzione per impostare DataContext nel codice dietro? Posso farlo funzionare, ma preferirei tenerlo in XAML.

+2

puoi sempre spostare la tua risorsa VM su app.xaml se applicabile. Su un sidenote si prega di nominare le classi VM come 'SomethingViewModel' e non solo lo stesso nome della View e utilizzare namespace per differenziare le classi. È davvero strano e spaventoso – Viv

+0

Josh Smith ha avuto un esempio di questo vedrò se riesco a trovarlo, fondamentalmente quando il datatemplate è stato applicato nello XAML anche il titolo è stato applicato .. –

risposta

12

Si può cercare di impostare la sintassi elemento DataContext utilizzando la proprietà:

<Window x:Class="MyProject.View.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel" 
    Title="{Binding Path=Title}" Height="350" Width="525"> 
<Window.Resources> 
    <vm:MainWindow x:Key="mainWindowViewModel"/> 
</Window.Resources> 
<Window.DataContext> 
    <StaticResourceExtension ResourceKey="mainWindowViewModel"/> 
</Window.DataContext> 

che dovrebbe funzionare come il parser XAML eseguirà StaticResourceExtension dopo che il dizionario risorse è impostato.

ma credo che forse anche migliore sarebbe quella di impostare il DataContext direttamente, senza dichiararlo come risorsa:

<Window x:Class="MyProject.View.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel" 
    Title="{Binding Path=Title}" Height="350" Width="525"> 
<Window.DataContext> 
    <vm:MainWindow x:Key="mainWindowViewModel"/> 
</Window.DataContext> 
+0

Il tuo primo suggerimento lancia la stessa eccezione. È interessante notare che la finestra mostra la risorsa nella vista Locali quando utilizzo Break. Il secondo suggerimento fornisce tre errori in fase di compilazione: "L'attributo" Chiave "può essere utilizzato solo su un elemento contenuto in IDictionary"; "L'attributo chiave può essere utilizzato solo su un tag contenuto in una proprietà di tipo IDictionary" e "L'attributo chiave può essere utilizzato solo su un tag contenuto in un dizionario (ad esempio un ResourceDictionary" – Tim

+1

@Tim Ho fatto un errore in ResourceKey = "mainWindowModel" .. dovrebbe indicare ResourceKey = "mainWindowViewModel" .Se hai solo copiato e incollato prova a correggerlo, ma non sono molto sicuro di questo, penso che una volta ho capito che funzionava così. – jure

+0

è davvero una buona notizia Sto rivisitando questa domanda, perché ho difficoltà a fare riferimento al modello di vista dichiarato a livello di codice, quindi renderlo di nuovo puro XAML può aiutare il mio altro problema. – Tim

0

Un po 'tardi, ma una soluzione semplice e perfetta che sto utilizzando nel caso in cui le persone sono ancora ricerca di possibilità:

<Window x:Class="Project.MainWindow" 
     Title="{Binding DataContext.ApplicationTitle, ElementName=TheMainView}"> 

     <views:MainView x:Name="TheMainView"/> 

</Window> 

che sufficiente semplicemente, è sufficiente aggiungere un immobile alla sua MainViewModel che è il DataContext del MainView in questo modo:

public string ApplicationTitle 
     { 
      get 
      { 
       var text = "Application Name"; 
       if (!string.IsNullOrEmpty(_currentFileLoaded)) 
       { 
        text += $" ({_currentFileLoaded})"; 
       } 

       return text; 
      } 
     } 

Spero che sia d'aiuto ..