2016-10-04 1 views
1

J'ai deux propriétés publiques Foo et Bar dans ma ViewModel. Foo est juste une chaîne et Bar est une classe qui a une propriété publique Name qui est une chaîne.Accès aux propriétés des propriétés dans DataBinding

Je veux lier Bar.Name à un élément GUI. Comment est-ce que je fais cela?

<Label Content="{Binding Foo}"> écrit la chaîne Foo dans l'étiquette, comme prévu.

Mais <Label Content="{Binding Bar.Name}"> n'écrit pas le nom de Bar dans l'étiquette. Au lieu de cela, l'étiquette reste vide.

EDIT: Le DataContext de mon XAML (et donc de l'étiquette) est défini sur le ViewModel.

EDIT2: Bien sûr, le code réel n'est pas aussi simple que décrit ci-dessus. J'ai construit un exemple de travail minimal qui ne représente que la description ci-dessus:

XAML:

<Window x:Class="MyTestNamespace.MyXAML" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> 
    <StackPanel> 
     <Label Content="{Binding Foo}"></Label> 
     <Label Content="{Binding Bar.Name}"></Label> <!-- Works fine! --> 
    </StackPanel> 
</Window> 

ViewModel:

namespace MyTestNamespace 
{ 
    class MyVM 
    { 
     public string Foo { get; set; } 
     public MyBar Bar { get; set; } 

     public MyVM() 
     { 
      Foo = "I am Foo."; 
      Bar = new MyBar("I am Bar's name."); 
     } 
    } 

    class MyBar 
    { 
     public string Name { get; set; } 

     public MyBar(string text) 
     { 
      Name = text; 
     } 
    } 
} 

Cela fait ne fonctionne comme prévu. Puisque je ne peux pas partager le code réel avec vous (trop et appartenant à l'entreprise), j'ai besoin de chercher la cause par moi-même. Tous les indices sur les raisons possibles sont les bienvenus!

+0

Etes-vous sûr que la propriété Nom de l'instance de classe Bar dans votre viewmodel est rempli (et la propriété Bar est correctement instancié)? Comment est défini le DataContext sur votre étiquette (ou l'un des parents ou le DataTemplate)? –

+0

Oui, tout est configuré correctement. Je peux travailler normalement avec 'Bar.Name' dans le code. Ni 'Bar' ni' Bar.Name' ne sont null, jamais. – Kjara

+0

Veuillez partager le code pour plus de détails –

Répondre

0

1.Your Model.cs:

public class Model : INotifyPropertyChanged 
{ 
    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      _name = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("Name")); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 

2.Votre ViewModel:

public MainViewModel() 
    { 
    _model = new Model {Name = "Prop Name" }; 
    } 



    private Model _model; 
    public Model Model 
    { 
     get 
     { 
      return _model; 
     } 
     set 
     { 
      _model = value;  
     } 
    } 

3.Votre Voir, avec DataContext réglé sur votre ViewModel:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    Title="MainWindow" 
    DataContext="{StaticResource MainViewModel}"> 
<Grid> 
    <Label Content="{Binding Model.Name}"/> 
</Grid> 

0

Merci au commentaire de Vignesh N. J'étais capable de résoudre le problème.

Dans le code réel Bar peut changer, mais au début, son nom est une chaîne vide. C'est ce que l'étiquette montre quand la fenêtre est ouverte. Parce que le Label n'est pas averti lorsque la propriété Bar change, il ne se met pas à jour.

Solution: ViewModel implémenter l'interface INotifyPropertyChanged et définir Bar comme ceci:

private MyBar _bar; 
public MyBar Bar 
{ 
    get 
    { 
     return _bar; 
    } 

    set 
    { 
     if (_bar != value) 
     { 
      _bar = value; 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Bar))); 
     } 
    } 
}