Member 11968388 Ответов: 1

Динамическое связывание combobox в MVVM, WPF и EF


Привет Сообщество,
В моем приложении у меня есть два comboboxes. Второй зависит от значения предыдущего выбранного значения. Но cb2 не обновляется, когда я выбираю что-то в cb1.
Когда я запускаю свое приложение, cb1 правильно заполняется всеми клиентами, которые существуют в моей базе данных (привязка с EnitiyFramework работает), и когда я выбираю там значение, свойство "ClientForwarders" обновляется для всех форвардеров, принадлежащих выбранному клиенту, но combobox их не показывает.

моя модель:
public class Client
    {
        public int ClientId { get; set; }
        public string ClientName { get; set; }

        public virtual ICollection<CommandMapping> CommandMappings { get; set; }
    }

 public class Forwarder
    {
        public int ForwarderId { get; set; }
        public string ForwarderName { get; set; }

        public virtual ICollection<CommandMapping> CommandMappings { get; set; }
    }

 public class CommandMapping
    {
        public int CommandMappingId { get; set; }
        public string CommandMappingName { get; set; }
        
        public virtual Client Client { get; set; }
        public virtual Forwarder Forwarder { get; set; }
    }

Смотреть:
<Window [...]>
	<Window.DataContext>
		<vm:MainWindowViewModel/>
	</Window.DataContext>
	<ComboBox Name="cb1" ItemsSource="{Binding Clients, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="ClientName"  SelectedItem="{Binding SelectedClient}"/>
	<ComboBox Name="cb2" ItemsSource="{Binding ClientForwarders, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="ForwarderName" SelectedItem="{Binding SelectedForwarder}"/>
</Window>

И моя модель представления:
namespace ProjectXY.ViewModel
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        #region ClientHandling
        public IEnumerable<Client> Clients { get; private set; }
        private Client _selectedClient;
        public Client SelectedClient
        {
            get => _selectedClient;
            set
            {
                _selectedClient = value;
                OnPropertyChanged(nameof(SelectedClient));
            }

        }
        #endregion

        #region ForwarderHandling
        public IEnumerable<Forwarder> ClientForwarders { get; private set; }
        private Forwarder _selectedForwarder;
        public Forwarder SelectedForwarder
        {
            get => _selectedForwarder;
            set
            {
                _selectedForwarder = value;
                OnPropertyChanged(nameof(SelectedForwarder));
            }
        }
        #endregion

        private EFDataModel _ctx;

        public MainWindowViewModel()
        {
            LoadData();
        }

        protected void LoadData()
        {
            Refresh();
        }
        public void Refresh()
        {
            _ctx = new DataModel();
            _ctx.Clients.Load();
            _ctx.Forwarders.Load();
            _ctx.CommandMappings.Load();
            Clients = _ctx.Clients.Local.ToList();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            switch (propertyName)
            {
                case null:
                    return;
                case nameof(SelectedClient):
                    var forwarderIdList = new List<int>();
                    Task.WaitAll(_ctx.CommandMappings
                        .Where(cm => cm.Client.ClientId == SelectedClient.ClientId)
                        .ForEachAsync(x => forwarderIdList.Add(x.Forwarder.ForwarderId)));
                    ClientForwarders = _ctx.Forwarders.Local.Where(x => forwarderIdList.Contains(x.ForwarderId)).ToList();
                    
                    break;
            }
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }
}


Что я уже пробовал:

Для отладки я заполнил свойство "ClientForwarders" непосредственно в методе "Refresh ()". Это приводит к тому, что (как и ожидалось) все форвардеры отображаются в cb2.

1 Ответов

Рейтинг:
1

Ritesh Sahay

Вам нужно позвонить событие изменения свойства на недвижимость ClientForwarders, чтобы обновить поле со списком. Вы можете поднять то же самое в сеттере вашего свойства или после загрузки списка ClientForwarders.