Привязка данных WPF к свойству списка, не отображающемуся в WPF, но свойство резервной копии содержит данные - PullRequest
0 голосов
/ 06 ноября 2019

Я изучал 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;
            }
        }

    }
...