如何使用WPF MVVM缩短代码?

3

我不确定这个问题是否属于这里,请告诉我如果不是,但我正在苦苦挣扎于WPF和MVVM。

现在我有一个名为Customer的类,其中包含大约20个属性:

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

根据 MVVM 模式,我需要在我的 ViewModel 中复制所有这些属性,例如(为了避免问题过长,我只添加了 name 属性。但是请考虑如果我要将 Model 的所有 20 个属性添加到我的 ViewModel 中,像以下这样):

public class CustomerViewModel : ViewModelBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }
    ...
}

你可以看到,仅仅是这个例子,我就会写出数百行代码。如果我需要将视图的数据保存到数据库中,我会这样做:

private void SaveCustomer()
{
    Customer customer = new Customer();
    customer.Id = Id;
    customer.Name = Name;
    customer.Address = Address;
    ...
}

又是一堆代码。如果我需要加载一个客户,我需要做同样的操作,只不过是反过来。如果我需要清空所有属性,我需要将每个属性设置为null。

在我的项目中,我就是这样做的,我不知道这是否是正确的方法,如果有其他方法,请告诉我。但是这会创建大量代码,而且我无法看出如此多的代码是可维护的,因为很容易迷失在代码之中。如果有其他方法或者我的想法是错误的,请告诉我。


让客户实现INotifyPropertyChanged接口,你的ViewModel应该只保留一个模型集合(例如ObservableCollection<Customer>),假设你想要显示多个。可选地,它还可以包含:SelectedCustomer(绑定到某个ListView的双向绑定),一些命令(ICommand实现),一些代码后台状态管理逻辑(启用/禁用视图、进度指示器等)。所有与客户相关的逻辑(业务逻辑)都应该解耦并通过某种形式的依赖注入(Google控制反转)提供给ViewModel。 - shadow32
感谢您的评论。然而,我宁愿不使用代码后端,并且我只想显示单个客户。主要目的是通过文本字段等显示客户并使其可编辑。@shadow32 - Tom el Safadi
如果你将项目发送到michael_puckett_ii@hotmail.com,我会为你构建一个可靠的MVVM稳定版本,并作为一个单独的项目发送回来,供使用或只是借鉴,但基于你自己的项目,这样更容易跟随。然后,如果你愿意,你可以在这里发布你发现的答案。 - Michael Puckett II
2个回答

1

Model 属性包装到您的 ViewModel 属性中,使属性彼此隔离。

public class Customer 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    ...
}
public class CustomerViewModel : ViewModelBase
{
    private Customer _customer;
    public string Name
    {
        get => _customer.Name;
        set
        {
            if(_customer.Name != value)
            {
                 _customer.Name = value;
                 OnPropertyChanged();
            }
        }
    }
}

然后你可以省略SaveLoad方法,或者只需在其中调用Repository.Save / Load。这样做的想法是,每个属性都可以单独测试。

1

没有任何规定说你的模型 POCOs 和视图模型 POCOs 必须不同。我会只使用 Customer,并让一个视图模型拥有它:

public class CustomerPageViewModel
{
     public Customer Customer
     {
         //get/set
     }
}

那样,UI 中的任何更改都已经在该对象中,您可以将其传递给将持久保存更改的任何服务。如果只有 UI 进行更改,则不需要实现 INPC。Customer 可以实现 INPC,但如果除 UI 之外没有任何更改,则不需要实现。另外,不要以长度为衡量代码质量的标准,有时 VM 上有很多属性。应该以易于维护、扩展等方面来衡量。

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