【问题标题】:C# - WPF/WP Binding from database - proper way? MVVMC# - 来自数据库的 WPF/WP 绑定 - 正确的方法? MVVM
【发布时间】:2015-05-11 03:43:51
【问题描述】:

假设我将这个类作为 Model(由它生成的数据库):

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

ViewModel 中,我有一个 ObservableCollection 客户,其中包含数据库中的所有客户:

ObservableCollection<Customer> Customers;

“客户”是从数据库中填充的。

视图中,ListBox 由客户填充:

<ListBox ItemsSource="{Binding Customers}" />

这就是问题所在。假设我想向数据库中插入一个新客户,我应该采取什么方法来通过 UI 跟踪更改:

重置 ItemsSource:(目前使用这种 - 最糟糕的方法)

ListBoxExample.ItemsSource = null;
ListBoxExample.ItemsSource = Customers;

通过 ObservableCollection 客户跟踪更改

例如,如果我想在数据库中插入一些东西,也将其插入到客户中,UI 会收到有关更改的通知。

还有哪些其他选择?

实现以下目标的最佳 MVVM 方法是什么:

  • 解析 JSON 数据并将其插入本地数据库
  • 从本地数据库中检索数据并用它填充 ListBox/ListView
  • 如果将新数据插入数据库或删除/更改项目,请更新 ListBox/ListView 中的更改

如果我想在数据库中添加项目,我可以简单地将项目添加到客户列表并将其添加到数据库中。但是,假设我从数据库中删除了一个对象,可观察集合“客户”将不会收到通知并且将不同步(UI 也不会更新)。有没有办法深入挖掘 MVVM 结构,而不是在可观察集合和数据库中添加/删除/更改项目,以某种方式使可观察集合跟踪数据库中的更改(例如,如果更改是通过其他应用程序完成的)。

【问题讨论】:

  • 我认为您对如何在 MVVM 项目中使用项目填充 ListBox 的理解可能存在一些问题。这应该通过绑定来完成,而不是直接引用 ViewModel 中的 ListBox。如果您的集合是客户,您的 ListBox 声明应如下所示: 。然后你在你的集合上使用 Add/Remove/Clear 方法来管理它的内容。
  • 如果添加项目,请将它们添加到可观察集合中。如果您删除它们,请将它们从集合中删除。通过 xaml 中的绑定而不是代码隐藏来执行此操作。如果您不使用绑定,那么您在 WPF 中执行 MVVM 是错误的。 &lt;ListBox ItemsSource="{Binding Customers}"
  • 更新了线程以防止混淆。我不认为你有我的问题。如果我想在数据库中添加项目,我可以简单地将项目添加到客户列表并将其添加到数据库中。但是,假设我从数据库中删除了一个对象,可观察集合“客户”将不会收到通知并且将不同步(UI 也不会更新)。有没有办法深入挖掘 MVVM 结构,而不是在可观察集合和数据库中添加/删除/更改项目,以某种方式使可观察集合跟踪数据库中的更改(例如,如果更改是通过其他应用程序完成的)。
  • @Millkovac 您是否找到任何最佳做法?
  • 我对我找到的解决方案并不满意,但这是我所做的更改。在 ViewModel 中,我有一个 ObservableCollection,当应用程序运行时,它会从数据库中加载项目。然后,我使用绑定将 ListBox 的 ItemsSource 属性设置为该 ObservableCollection。现在不再只是向数据库中删除/添加项目,每当我从数据库中添加/删除某些内容时,它也会在 ObservableCollection 中进行更改。这样,每当数据库发生变化时,UI 都会收到通知,因为这些变化也会反映在 ObservableCollection 中。

标签: c# wpf mvvm binding observablecollection


【解决方案1】:

嗯,我不知道您是否需要解决方案,但根据您上次的评论,您并不满意...我将说明我的方法。

public class CustomersVm : INotifyPropertyChange
{ // just to point out, that you're using a VM class here   
   private ObservableCollection _customers;
   public ObservableCollection Customers
   { // since you're binding this to your listbox, DON'T change the reference during runtime
       get { return _customers ?? (_customers = new ObservableCollection());
   }

   // here comes your loading logic
   public void RefreshCustomers()
   {
       var customers = LoadCustomersFromDb(); // contains now a result set of model classes

       Customers.Clear(); //Clear the collection instead of creating it again.
       foreach(var customer in customers)
           Customers.Add(customer);
   }
}

现在在 XAML 中的用法,如果 WindowDataContext 设置为 CustomersVm 的实例,则该用法有效。 (注意:更一般地说,父元素的DataContext 需要这样设置。)

<Window DataContext=... >
    <ListBox ItemsSource={Binding Customers} />
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 2023-03-21
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多