#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
norBar.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>