Я изучал WPF, но застрял на привязке данных, которая, похоже, не работает. Текст данных для представления работает правильно для других свойств, но не для свойства списка.
Открытый объект-оболочка в модели представления (для Name и Capacity {Binding Pot.Name} работает правильно)
class Pot {
public int Id;
public string Name;
public float Capacity;
IEnumerable<LookupItem> Readings;
}
class LookupItem{
public int Id;
public string DisplayMember;
}
Назначается в виде представления данных в текстовом виде в представлении из моей службы поиска данных. Это успешно завершается, и Pot.Readings имеет начальные данные для правильного объекта.
Pot.Readings = await _readingLookupDataService.GetReadingsLookupByIdAsync(Pot.Id);
В представлении управления пользователем
<Label Content="Pot Name" Margin="10 10 10 0"/>
<TextBox Grid.Row="1" Text="{Binding Pot.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="10 0 10 10"/>
<Label Grid.Row="2" Content="Pot Capacity" Margin="10 10 10 0"/>
<TextBox Grid.Row="3" Text="{Binding Pot.Capacity,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="10 0 10 10"/>
<ListView Grid.Row="4" ItemsSource="{Binding Pot.Readings}" DisplayMemberPath="DisplayMember"/>
Свойство Readings получает данные, и их нетлюбые ошибки связывания. Он просто не помещает показания в ListView, ItemsControl, ListBox, TextBlock или StackPanel из TextBoxes / Buttons. Я также попытался присвоить Pot.Readings общедоступному списку чтений в модели представления с теми же результатами. Элемент управления не показывает данных из привязки. Спасибо за любую помощь
--- Редактировать текст данных, используемый wpf и классом modelwrapper ниже:
public class PotDetailViewModel : ViewModelBase, IPotDetailViewModel
{
private IPotRepository _potRepository;
private IEventAggregator _eventAggregator;
private IMessageDialogService _messageDialogService;
private bool _hasChanges;
private PotWrapper _pot;
public PotWrapper Pot
{
get { return _pot; }
private set
{
_pot = value;
OnPropertyChanged();
}
}
private IPotDetailReadingsViewModel _potDetailReadingsViewModel;
public IPotDetailReadingsViewModel PotDetailReadingsViewModel
{
get { return _potDetailReadingsViewModel; }
set { _potDetailReadingsViewModel = value; }
}
public ICommand SaveCommand { get; }
public ICommand DeleteCommand { get; }
private IReadingLookupDataService _readingLookupDataService;
public bool HasChanges {
get { return _hasChanges; }
set
{
if (_hasChanges != value)
{
_hasChanges = value;
OnPropertyChanged();
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
}
public PotDetailViewModel(IPotRepository potRepository, IEventAggregator eventAggregator, IMessageDialogService dialogService, IReadingLookupDataService readingLookupDataService)
{
_potRepository = potRepository;
_eventAggregator = eventAggregator;
_messageDialogService = dialogService;
// DelegateCommand is part of Prism to handle actions
SaveCommand = new DelegateCommand(OnSaveExecute, OnSaveCanExecute);
DeleteCommand = new DelegateCommand(OnDeleteExecute);
_readingLookupDataService = readingLookupDataService;
}
private async void OnDeleteExecute()
{
var result = _messageDialogService.ShowOkCancelDialog($"Confirm Delete : {Pot.Name}","Delete Pot");
if (result == MessageDialogResult.OK)
{
_potRepository.Remove(Pot.Model);
await _potRepository.SaveAsync();
_eventAggregator.GetEvent<AfterPotDeletedEvent>().Publish(Pot.Id);
}
}
private async void OnSaveExecute()
{
await _potRepository.SaveAsync();
HasChanges = _potRepository.HasChanges();
_eventAggregator.GetEvent<AfterPotSavedEvent>().Publish(new AfterPotSavedEventArgs { Id = Pot.Id, DisplayMember = Pot.Name });
}
private bool OnSaveCanExecute()
{
return Pot!=null && !Pot.HasErrors && HasChanges;
}
public async Task LoadAsync(int? potId)
{
var pot = potId.HasValue ? await _potRepository.GetByIdAsync(potId.Value) : CreateNewPot();
Pot = new PotWrapper(pot);
Pot.Readings = await _readingLookupDataService.GetReadingsLookupByIdAsync(Pot.Id);
Pot.PropertyChanged += (s, e) =>
{
if (!HasChanges)
{
HasChanges = _potRepository.HasChanges();
}
if (e.PropertyName == nameof(Pot.HasErrors))
{
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
};
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
if (Pot.Id ==0)
{
// Triggers Validation
Pot.Name = "";
}
}
private Pot CreateNewPot()
{
var pot = new Pot();
_potRepository.Add(pot);
return pot;
}
}
}
public class PotWrapper : ModelWrapper<Pot>
{
private IEnumerable<LookupItem> _readings;
public PotWrapper(Pot model) : base(model)
{
_readings = new List<LookupItem>();
}
public int Id { get { return Model.Id; } }
public string Name {
get { return GetValue<string>(); }
set
{
SetValue(value);
}
}
public float Capacity
{
get { return GetValue<float>(); }
set
{
SetValue(value);
}
}
public IEnumerable<LookupItem> Readings
{
get { return _readings; }
set
{
_readings = (value);
}
}
// Constructor
// Methods
protected override IEnumerable<string> ValidateProperty(string propertyName)
{
switch (propertyName)
{
case nameof(Name):
if (string.IsNullOrEmpty(Name))
{
yield return "Name cannot be empty";
}
break;
default:
break;
}
}
}