在MVVM

时间:2015-11-06 09:59:03

标签: c# wpf mvvm

这是一个简化的ViewModel:

public class EditViewModel : BaseViewModel
{
    private Item _currentItem;
    public Item CurrentItem
    {
        get
        { return _currentItem; }
        set
        {
            if (_currentItem != value)
            {
                _currentItem = value;
                OnPropertyChanged("CurrentItem");
            }
        }
    }

    private ObservableCollection<Property> _itemProperties;
    public ObservableCollection<Property> ItemProperties
    {
        get { return _itemProperties; }
        set
        {
            _itemProperties = value;
            OnPropertyChanged("ItemProperties");
        }
    }

    public void AddProperty() //this is called from an ICommand
    {
        Property p = new Property{ ItemId = CurrentItem.ItemId };;
        CurrentItem.Properties.Add(p);
        ItemProperties.Add(p);
    }
}

我想要做的是将业务逻辑分离到一个单独的类中。它使所有讨厌的MVVM样板不受有用的东西影响,理论上应该导致将代码组织成一个更可测试的状态。

我们开始通过创建单独的“Logic”类来实现这一点,这些类继承自BaseViewModel,然后让实际的ViewModel继承自它们的逻辑类。所以:

public class EditLogic : BaseViewModel
{ }

public class EditViewModel : EditLogic
{ }

然后逻辑进入逻辑类。

对于某些业务逻辑,这种分离很简单 - 干净整洁。但是,在我上面给出的例子中,我看不出一种简单的方法来拉出那个方法而没有很多不必要的faff。像这样(未经测试):

public class EditLogic : BaseViewModel
{
    public Property GetNewProperty(Item currentItem)
    {
        Property p = new Property{ ItemId = currentItem.ItemId };
        currentItem.Properties.Add(p); 
        return p;
    }
}

public class EditViewModel : BaseViewModel
{
    public void AddProperty() //this is called from an ICommand
    {
        ItemProperties(GetNewProperty(CurrentItem))
    }
}

这似乎有点令人困惑 - 因为它依赖于隐式地通过引用传递的CurrentItem - 并且不必要地卷曲到没有很大的收益。

这当然是一个非常简单的例子,不值得大惊小怪。但它说明了在MVVM中,为方便起见,最终很容易将您的表示/绑定代码与业务逻辑混合在一起。

我可以将一些属性从EditViewModel移到EditLogic,但是我们首先失去了将这两个属性分开的优势。

所以:这根本不值得打扰吗?如果是这样,我们应该追求多远?是否有更好的方法来保持分离?

1 个答案:

答案 0 :(得分:3)

您正在寻找的是服务

public interface IPropertyService
{
    Property GetNewProperty(Item currentItem);
}

您当然需要实施:

public class MyPropertyService : IPropertyService
{
    public Property GetNewProperty(Item currentItem)
    {
        //TODO
    }
}

然后,您可以将此服务作为依赖项注入视图模型的构造函数中。

public class MyViewModel
{
    private IPropertyService _PropertyService;

    public MyViewModel(IPropertyService propertyService)
    {
        _PropertyService = propertyService;
    }

    public void AddProperty() //this is called from an ICommand
    {
        Property p = _PropertyService.GetProperty(CurrentItem);
        CurrentItem.Properties.Add(p);
        ItemProperties.Add(p);
    }
}

这将确保您不需要为业务逻辑创建无数的视图模型基类。相反,将业务逻辑封装在服务中,并将它们传递给依赖于它们的视图模型。