【问题标题】:ComboBox Items not updated when Collection changes using ObservableCollection使用 ObservableCollection 更改 Collection 时未更新 ComboBox 项
【发布时间】:2017-05-19 10:14:40
【问题描述】:

我在 .NET WPF 应用程序中绑定的 Datagrid 中有 ComboBox,如下所示:

<ComboBox x:Name="categoryValues" MinWidth="70" 
          IsSynchronizedWithCurrentItem="False"                   
          SelectedValuePath="Id"
          ItemsSource="{Binding Source={StaticResource categoryViewSource},
                Converter={StaticResource CategoriesToCategoriesConverter}}"
          SelectedItem="{Binding Category,
                Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged,
                Converter={StaticResource CategoryToCategoryConverter}}"
          DisplayMemberPath="Name" SelectionChanged="categoryValues_SelectionChanged">
</ComboBox>

所以每一行都绑定到不同模型中的字段类别。 categoryViewSource 定义如下

<CollectionViewSource x:Key="categoryViewSource" d:DesignSource="{d:DesignInstance {x:Type Models:Category}, CreateList=True}"/>

我的类别模型使用 PropertyChanged.Fody NuGet 包实现 INotifyPropertyChanged。使用 Entity Framework 从数据库加载数据后,我将数据分配给 CollectionViewSource,如下所示:

var db = new MyDbContext();
System.Windows.Data.CollectionViewSource categoryViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["categoryViewSource"];
await db.Categories.LoadAsync();
categoryViewSource.Source = db.Categories.Local;

所以它绑定到 Observable 集合。但是,一旦我这样做了

var c = new Category { Name="New Category" };
db.Categories.Add(c);

我的 CollectionViewSource 已更新(至少在调试器中),这似乎合乎逻辑,它的源是 ObservableCollection。但即使我这样做了

categoryViewSource.View.Refresh();

我的 ComboBox ItemsSource 没有更新。我尝试使用 IsSynchronizedWithCurrentItem="True",如 StackOverflow 上的某处所示。到目前为止,它只有在我做这样的事情时才有效:

categoryViewSource.Source = null;
categoryViewSource.Source = db.Categories.Local;

但是我的 SelectedItem 属性在所有 ComboBox 中都为空,并且它们在 Datagrid 中显示为空,因为显然 SelectedItem 的实例在您重新分配集合后是不同的。

谁有解决办法。不幸的是,我对 WPF 还是很陌生,不知道。

【问题讨论】:

    标签: c# .net wpf xaml combobox


    【解决方案1】:

    DbSet&lt;Category&gt; 添加新的Category 不会影响ObservableCollection&lt;Category&gt;。这是两个不同且独立的内存集合。您必须将相同的对象添加到两个集合中。

    您可以创建一个ObservableCollection 并在初始化ComboBox 时用您的实体对象填充它。然后将任何新对象添加到上下文和数据绑定集合中,即:

    public partial class MainWindow : Window
    {
        ObservableCollection<Category> _cats;
        public MainWindow()
        {
            InitializeComponent();
    
            var db = new MyDbContext();
            System.Windows.Data.CollectionViewSource categoryViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["categoryViewSource"];
            await db.Categories.LoadAsync();
            _cats = new ObservableCollection<Category>(db.Categories.Local);
            categoryViewSource.Source = _cats;
            //...
            var c = new Category { Name = "New Category" };
            db.Categories.Add(c); //add to DbSet
            _cats.Add(c); //add to ObservableCollection
        }
    }
    

    好的,如果我直接将它添加为 ItemsSource,那确实有效。但是,如果我通过单独的绑定添加集合,它就不起作用。我需要通过转换器传递集合。有没有办法自动完成?

    您可以通过编程方式设置绑定:

    categoryValues.SetBinding(ComboBox.ItemsSourceProperty, new Binding(".") { Source = _cats, Converter = new CategoriesToCategoriesConverter() });
    

    【讨论】:

    • 我试过了,没用。问题是,ObservableCollection&lt;Category&gt; 确实得到了更新。我的db.Categories.LocalObservableCollection&lt;Category&gt;,它会更新,而`CollectionViewSource.Source` 只是一个参考,对吧?无论如何,如果我在db.Categories.Add(c) 之后进行调试,我的 categoryViewSource 确实会在其View.InternalList 中显示一个新项目。我在转换器中为 ItemsSource 设置了一个断点,以查看是否有什么东西,但转换器从不触发,所以不知何故绑定到 categoryViewSource 不起作用?
    • db.Categories 与 ObservableCollection 不是同一个集合。如果直接将 ComboBox 的 ItemsSource 属性设置为 ObservableCollection 会怎样:categoryValues.ItemsSource = _cats;
    • 好的,如果我直接将它添加为 ItemsSource,那确实有效。但是,如果我通过单独的绑定添加集合,它就不起作用。我需要通过转换器传递集合。有没有办法自动完成?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 2013-11-30
    相关资源
    最近更新 更多