Динамическое связывание 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.