Доступ к свойствам свойств в привязке данных

#c# #wpf #data-binding #properties

#c# #wpf #привязка данных #свойства

Вопрос:

У меня есть два общедоступных свойства Foo и Bar в моей ViewModel. Foo это просто строка и Bar класс, который имеет общедоступное свойство Name , которое является строкой.

Я хочу привязаться Bar.Name к какому-либо элементу графического интерфейса. Как мне это сделать?

<Label Content="{Binding Foo}"> записывает строку Foo в метку, как и ожидалось.

Но <Label Content="{Binding Bar.Name}"> не записывает имя Bar в метку. Вместо этого метка остается пустой.

РЕДАКТИРОВАТЬ: DataContext для моего XAML (и, следовательно, для метки) устанавливается значение ViewModel.

РЕДАКТИРОВАНИЕ 2: Конечно, реальный код не так прост, как описано выше. Я создал минимальный рабочий пример, который представляет только приведенное выше описание:

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;
        }
    }
}
  

На самом деле это работает так, как ожидалось. Поскольку я не могу поделиться с вами фактическим кодом (слишком много и принадлежит компании), мне нужно искать причину самостоятельно. Любые намеки на возможные причины приветствуются!

Комментарии:

1. Вы уверены, что свойство Name экземпляра класса Bar в вашей viewmodel заполнено (и экземпляр свойства Bar создан правильно)? Как DataContext устанавливается на вашей метке (или на одном из родительских элементов или DataTemplate)?

2. Да, все настроено правильно. Я могу нормально работать с Bar.Name кодом. Ни Bar nor Bar.Name , ни null, никогда.

3. Пожалуйста, поделитесь кодом для получения дополнительной информации

4. является ли значение для Name set в конструкторе Bar или впоследствии, если да, вызываете ли вы событие изменения свойства после установки значения?

Ответ №1:

Благодаря комментарию Виньеша Н. Я смог решить проблему.

В самом коде Bar может измениться, но в начале его имя является пустой строкой. Это то, что отображается на ярлыке при открытии окна. Поскольку объект Label не получает уведомления при изменении Bar свойства, он не обновляется.

Решение: заставьте ViewModel реализовать INotifyPropertyChanged интерфейс и определить Bar его следующим образом:

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

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

Ответ №2:

1.Ваш 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.Ваша ViewModel:

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



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

3. Ваше представление с DataContext, установленным для вашей 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>