2010-07-16 6 views
1

Je lie une vue à un viewmodel et je n'arrive pas à initialiser une zone de liste déroulante à une valeur par défaut. Une simplification de la classe que je utilise dans la liaison estLa zone de liste des données de Siliverlight n'affiche pas la valeur initialisée

public class LanguageDetails 
{ 
    public string Code { get; set; } 
    public string Name { get; set; } 
    public string EnglishName { get; set; } 

    public string DisplayName 
    { 
    get 
    { 
     if (this.Name == this.EnglishName) 
     { 
     return this.Name; 
     } 
     return String.Format("{0} ({1})", this.Name, this.EnglishName); 
    } 
    } 
} 

Le combobox est déclaré en XAML comme

<ComboBox x:Name="LanguageSelector" Grid.Row="0" Grid.Column="1" 
      SelectedItem="{Binding SelectedLanguage,Mode=TwoWay}" 
      ItemsSource="{Binding AvailableLanguages}"> 
    <ComboBox.ItemTemplate> 
    <DataTemplate> 
     <TextBlock Text="{Binding DisplayName}"/> 
    </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

et viewmodel contient ce code

private List<LanguageDetails> _availableLanguages; 
private LanguageDetails _selectedLanguage; 

public LoginViewModel() 
{ 
    _availableLanguages = LanguageManager.GetLanguageDetailsForSet(BaseApp.AppLanguageSetID); 
    _selectedLanguage = _availableLanguages.SingleOrDefault(l => l.Code == "en"); 
} 

public LanguageDetails SelectedLanguage 
{ 
    get { return _selectedLanguage; } 
    set 
    { 
    _selectedLanguage = value; 
    OnPropertyChanged("SelectedLanguage"); 
    } 
} 

public List<LanguageDetails> AvailableLanguages 
{ 
    get { return _availableLanguages; } 
    set 
    { 
    _availableLanguages = value; 
    OnPropertyChanged("AvailableLanguages"); 
    } 
} 

de la vue à la fin du constructeur à la fois les variables _availableLanguages ​​et _selectedLanguage sont définies comme prévu, la liste déroulante de la liste déroulante contient tous les éléments dans _availableLanguages ​​mais la valeur sélectionnée n'est pas affichée dans la combobox. La sélection d'un élément dans le menu déroulant l'affiche correctement et définit la propriété SelectedLanguage dans le modèle de vue. Un point d'arrêt dans le setter révèle que _selectedLanguage contient toujours ce à quoi il a été initialisé jusqu'à ce qu'il soit écrasé par une valeur.

Je soupçonne qu'il y a quelque chose qui me manque, mais après avoir essayé différentes choses et beaucoup de googler je suis toujours perplexe. Je pourrais atteindre le résultat souhaité d'autres façons, mais je veux vraiment avoir une idée de l'utilisation correcte de la liaison de données.

Répondre

2

Vous devez modifier l'ordre de vos liaisons dans XAML afin que votre ItemsSource se lie avant SelectedItem.

<ComboBox x:Name="LanguageSelector" Width="100" 
     ItemsSource="{Binding AvailableLanguages}" 
     SelectedItem="{Binding SelectedLanguage,Mode=TwoWay}"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding DisplayName}"/> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

Si vous définissez un point d'arrêt sur le « get » à la fois du SeletedLanguage et AvailibleLanguage, vous remarquerez que le SelectedLanguage est touché avant AvailibleLanguage. Puisque cela se produit, il est impossible de définir le SelectedLanguage parce que ItemsSource n'est pas encore rempli. Changer l'ordre des liaisons dans votre XAML fera en sorte que les langues disponibles seront d'abord touchées, puis le langage SelectedLanguage. Cela devrait résoudre votre problème.

+1

Merci. Je l'ai découvert via des points d'arrêt tels que vous les décrivez avant de voir votre réponse. Je dois dire qu'il me vient à l'esprit que l'ordre des attributs dans XAML est significatif; Je n'aurais jamais pensé que ce serait le cas. –

-1

1) Lorsque vous attribuez la SelectedLanguage, utilisez la propriété publique SelectedLanguage au lieu du _selectedLanguage privé, de sorte que le poseur est exécuté,

2) Vous devez déplacer l'affectation du selectedlanguage au moment où la La vue a été chargée. Vous pouvez le faire en implémentant le gestionnaire d'événements Loaded sur la vue. Si vous souhaitez être "compatible mvvm", vous devez utiliser un comportement de fusion qui mappera l'événement chargé de l'interface utilisateur à une implémentation de commande viewmodel dans laquelle vous définirez la langue sélectionnée.

+0

J'avais essayé la première option; ça n'a pas marché. Je veux éviter le code supplémentaire comme dans votre deuxième suggestion. Je crois que cela devrait être possible avec de simples reliures et la solution apportée par ma réponse acceptée le confirme. –

+0

Juste la première option ne suffit pas. La propriété SelectedLanguages ​​du ViewModel doit être définie une fois que la vue a été entièrement construite. Pourquoi "-1"? J'essaie juste d'aider. – Przemek

+0

J'apprécie la tentative d'aide mais les infobulles sur les boutons de haut/bas de vote indiquent "cette réponse est utile" pour le haut et "cette réponse n'est pas utile" pour le bas. Bien que votre solution puisse atteindre le résultat, elle ajoute de la complexité et n'atteint pas la cause première, c'est-à-dire l'ordre des attributs XAML. Donc je ne l'ai pas trouvé utile donc je l'ai marqué. –