当 ItemsSource 更改 MVVM 时,Combobox SelectedItem 不会更新

Posted

技术标签:

【中文标题】当 ItemsSource 更改 MVVM 时,Combobox SelectedItem 不会更新【英文标题】:Combobox SelectedItem doesn't update when ItemsSource changes MVVM 【发布时间】:2021-09-26 16:11:38 【问题描述】:

我在主视图模型中定义了一个 OvserableCollection 的 Aperture

主视图模型

public ObservableCollection<LookupItemViewModel> Apertures  get; 



public void LoadAperturesCollection()
        
            Apertures.Clear();
            var items = _apertureTableListService.GetAllApertures();
            Apertures.Add(new LookupItemViewModel(0, null, true));
            foreach (var item in items)
            
                Apertures.Add(new LookupItemViewModel(item.Id, item.DisplayName, item.Active));
            

            SessionViewModel.LoadActiveCollection(Apertures, nameof(Apertures));
        

我在 editviewmodel 中有一个 ActiveApertures 的 ObservableCollection - 这是 Apertures 中的一个集合,其字段 Active 设置为 true

编辑视图模型

public ObservableCollection<LookupItemViewModel> ActiveApertures  get; 



private void LoadActiveAperturesCollection(ObservableCollection<LookupItemViewModel> collection)
        
            ActiveApertures.Clear();
            foreach (var item in collection)
            
                if (item.Active)
                
                    ActiveApertures.Add(new LookupItemViewModel(item.Id, item.DisplayName, item.Active));
                
            
        

曝光表有一个 Aperture 属性,它是 Aperture 表的外键

在 exposureeditview 中是一个带有 ActiveApertures 的 ItemsSource 的组合框

曝光编辑视图

<ComboBox 
            x:Name="comboBoxExposureDataAperture"
            Grid.Column="3"
            Grid.Row="5"
            DisplayMemberPath="DisplayName"
            IsSynchronizedWithCurrentItem="True"
            IsTextSearchEnabled="True"
            IsTextSearchCaseSensitive="True"
            ItemsSource="Binding ActiveApertures"
            SelectedValue="Binding Exposure.ApertureId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
            SelectedValuePath="Id"
            Style="DynamicResource ComboboxData"
            VerticalAlignment="Bottom"
            Width="110"
            Margin="0,0,0,5"/>

如果我编辑 Aperture,Apertures 集合会更新,ActiveApertures 集合也会更新,但组合框中的 SelectedItem 现在为空。所有的视图模型都实现了 INotifyPropertyChanged()。

我一直在搜索互联网,但我还没有找到与此问题匹配的解决方案。 任何建议将不胜感激。

编辑 1

 private LookupItemViewModel selectedRecord;
        public LookupItemViewModel SelectedRecord
        
            get  return selectedRecord; 
            set
            
                if(value != selectedRecord)
                
                    selectedRecord = value;
                    OnPropertyChanged();
                
                
            
        

<ComboBox 
            x:Name="comboBoxExposureDataAperture"
            Grid.Column="3"
            Grid.Row="5"
            DisplayMemberPath="DisplayName"
            IsSynchronizedWithCurrentItem="True"
            IsTextSearchEnabled="True"
            IsTextSearchCaseSensitive="True"
            ItemsSource="Binding ActiveApertures"
            SelectedItem="Binding SelectedRecord"
            SelectedValue="Binding Exposure.ApertureId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
            SelectedValuePath="Id"
            Style="DynamicResource ComboboxData"
            VerticalAlignment="Bottom"
            Width="110"
            Margin="0,0,0,5"/>

 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        

EDIT2

 public void LoadAperturesCollection()
        
            Apertures.Clear();
            var items = _apertureTableListService.GetAllApertures();
            Apertures.Add(new LookupItemViewModel(0, null, true));
            foreach (var item in items)
            
                Apertures.Add(new LookupItemViewModel(item.Id, item.DisplayName, item.Active));
            

            SessionViewModel.LoadActiveCollection(Apertures, nameof(Apertures));
        

private void LoadActiveAperturesCollection(ObservableCollection<LookupItemViewModel> collection)
        
            ActiveApertures.Clear();
            foreach (var item in collection)
            
                if (item.Active)
                
                    ActiveApertures.Add(new LookupItemViewModel(item.Id, item.DisplayName, item.Active));
                
            
        

【问题讨论】:

【参考方案1】:

那么为什么不将SelectItem 绑定到Combobox 中呢?

如果您在 viewModel 中实现了 INotifyPropertyChanged,请创建一个名为 SelectedRecord 的 ActiveApertures 项的示例并将其绑定到 ComboBox。如下图修改

EditViewModel 改为:

public class EditViewModel : INotifyPropertyChanged

    public ObservableCollection<LookupItemViewModel> ActiveApertures  get; 
    private LookupItemViewModel _selectedRecord;
    public LookupItemViewModel SelectedRecord
    
        get
        
            return _selectedRecord;
        
        set
        
            if(value != _selectedRecord)
            
                _selectedRecord = value;
                OnPropertyChanged("SelectedRecord");
            
        
    
    /.............................................................
    /.............................................................
    /.............................................................
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      

        

ComboBox 更改为:

<ComboBox 
            x:Name="comboBoxExposureDataAperture"
            Grid.Column="3"
            Grid.Row="5"
            DisplayMemberPath="DisplayName"
            IsSynchronizedWithCurrentItem="True"
            IsTextSearchEnabled="True"
            IsTextSearchCaseSensitive="True"
            ItemsSource="Binding ActiveApertures"
            SelectedValue="Binding Exposure.ApertureId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
            SelectedValuePath="Id"
            SelectedItem="Binding SelectedRecord"
            Style="DynamicResource ComboboxData"
            VerticalAlignment="Bottom"
            Width="110"
            Margin="0,0,0,5"/>

【讨论】:

Meysam,我做了你建议的更改,但我遇到了同样的问题。设置断点,调用 SelectedRecord get,但永远不会访问该集合。 还有其他建议吗? 我有 SelectedItem 绑定工作(不正确的 ViewModel)。但是当调用 SelectedRecord 属性时,ActiveApertures 集合为空。在 EDIT2 中,我有一个代码示例,用于在更改 Aperture 条目时更新 Apertures 和 ActiveApertures 集合。 为您的视图模型提供一个构造函数,并在其中 ActiveApertures = new ObservableCollection(); 我在视图模型中新建了一个 ObservableCollection()。 Apertures = new ObservableCollection();【参考方案2】:

我找到了一种使用 AfterDataSaved 事件更新 SelectedItem 的方法。

感谢所有努力提供帮助的人。

【讨论】:

以上是关于当 ItemsSource 更改 MVVM 时,Combobox SelectedItem 不会更新的主要内容,如果未能解决你的问题,请参考以下文章

使用 MVVM 将新项目添加到 TabControl ItemSsource 时选择最后一个 TabItem

更改 DataGrid.ItemsSource 时如何引发事件

MVVM Light,TreeView ItemSsource不更新

关于mvvm结构构建的想法

在 MVVM 中的 Datagrid 中绑定 WPF 组合框不保存更改

当 MVVM 中的属性更改时通知可观察集合