C# - WPF/WP 数据绑定 - 正确的方法是什么?MVVM

3

假设我有这个 Model 类(数据库由它生成):

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

ViewModel 中,我有一个ObservableCollection Customers用于保存来自数据库的所有客户:
ObservableCollection<Customer> Customers;

"Customers" 是从数据库中获取的。

在一个视图中,ListBox 是从 Customers 中获取的:

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

这里有一个问题。假设我想将新客户插入数据库,为了通过UI跟踪更改,应该采取什么方法:
重置ItemsSource:(目前使用的是最差的方法)
ListBoxExample.ItemsSource = null;
ListBoxExample.ItemsSource = Customers;

通过ObservableCollection Customers跟踪更改

例如,如果我想将某些内容插入到数据库中,也将其插入到Customers列表中,UI将会收到更改的通知。

还有哪些选项?

实现以下最佳MVVM方法:

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

如果我想向数据库中添加项目,只需将项目简单地添加到Customers列表中并将其添加到数据库即可。但是,假设我从数据库中删除了一个对象,则可观察集合“Customers”不会收到通知,而且将失去同步(UI也不会更新)。是否有一种方式可以深入了解MVVM结构,而不是在observable collection和数据库中添加/删除/更改项目,以某种方式使可观察集合跟踪数据库中的更改(例如,如果通过其他应用程序进行更改)。


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

0
嗯,我不知道你是否需要一个解决方案,但根据你最后的评论,你似乎不满意...我会说明我的方法。
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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接