【问题标题】:Validation design issue in combination with nested viewmodels结合嵌套视图模型的验证设计问题
【发布时间】:2014-11-05 14:03:30
【问题描述】:

在将 MVVM 与 WPF 结合使用方面,我有点初学者。我可以处理简单的事情,但我目前正在努力解决以下问题。

假设我有一个 TravelPlan 对象。 TravelPlan 有一个 Cities 对象(基本上是该计划将按特定顺序访问的所有城市的集合)。

城市使用动态控件呈现。它显示了可能城市的下拉框、加号 (+) 和减号 (-) 按钮。每当您按下 + 按钮时,都会出现一个新的空下拉列表供您选择。

我使用 TravelPlan 的视图模型和城市的单独视图模型创建了这个(见下文)。我添加了验证,以便您选择一个城市。

public class CityViewModel : DataErrorInfoViewModel
{
    private readonly IEnumerable<string> _availableCities;
    private string _selectedCity;

    public CityViewModel(IEnumerable<string> availableCities)
    {
        _availableCities = availableCities;
    }

    public string SelectedCity
    {
        get { return _selectedCity; }
        set
        {
            _selectedCity = value;
            RaisePropertyChanged(() => SelectedCity);
        }
    }

    public IEnumerable<string> AvailableCities
    {
        get { return _availableCities; }
    }

    protected override bool Validate(string propertyName)
    {
        var isValid = base.Validate(propertyName);
        if (MatchesProperty(() => SelectedCity, propertyName))
        {
            isValid = SelectedCity != null;
        }
        return isValid;
    }        
}

在 TravelPlan 视图模型中,我只使用 CityViewModel。

private ObservableCollection<CitiesViewModel> _cities;

在 TravelPlan 视图模型中,我还实现了 + / - 按钮。他们只需添加或删除城市视图模型。

这非常有效。

但是,我还想添加验证以查看所选城市的组合是否唯一(即,您不能两次选择同一个城市)。我无法将其添加到单个 CityViewModel 中,因为单个城市不知道所有其他选定的城市。

理想情况下,我想在自己的 ViewModel 中转换 CityViewModels 的 ObservableCollection。然后我可以将唯一验证添加到该特定视图模型。我相信我也可以将动态用户控件的逻辑移至该视图模型。

这将创建以下层次结构:TravelPlanViewModel - CitiesViewModels - CityViewmodel,其中每个视图模型都进行特定的验证。

这可能吗?是否推荐这样做?我想知道人们如何以 MVVM 方式解决这个特定的设计问题。 (我知道可以将唯一验证移动到 TravelPlan 视图模型中,但我想知道我描述的场景是否可行并且是一种常见做法)。

非常感谢代码示例!

【问题讨论】:

  • 你是对的,如果你有多个城市供用户选择,你必须在比 cityViewModel 本身更高的级别实现验证规则。为此,您可能希望在视图中更高的下一个 XAML 层实现 ValidationRule。 WPF 将调用 ValidationRules 并自动为您生成结果。看看这门课msdn.microsoft.com/en-us/library/…
  • @user1522548,我知道这一点。但是我在哪里进行验证?进入 TravelPlanViewModel?还是创建一个单独的 CitiesViewModel 更好?
  • 当然,我们还没有看到 CitesViewModel 或 TravelPlanViewModel 提供正确的建议。如前所述,您必须在位于 CityViewModel 位置的下一个容器中实现它。通常,正确的方法是在最接近需要的容器中进行。换句话说,如果您可以将其包含在层次结构中的较低位置,请不要将其置于顶层窗口层。我经常使用的技巧之一是创建实现组合行为的容器。按照您提到的顺序,我可能会创建一个 CitesViewModel,其中包含所需的所有 CityViewModel。
  • “遏制”或“偏好组合胜过继承”的力量非常有效!我使用这个概念的次数越多,我的应用程序就越好。所有你需要记住的是这个“是我正在处理的事物的一种类型或者它是否包含一种事物的类型。它包含一种事物的类型,只需将它作为属性放入,或者注入它通过构造函数。如果它是 - 那个东西的类型继承它。

标签: c# wpf mvvm


【解决方案1】:

实现集合视图模型并非闻所未闻——只需谷歌“CollectionViewModel”即可查看一些示例。但是,如果您所做的只是添加验证,我可能不会费心将集合包装在它自己的视图模型中。我只是将唯一性验证添加到您的根视图模型中,因为约束似乎与TravelPlan 的相关性更强。

所以,是的,这是可能的。我不知道它有多常见;我个人不这样做,但至少其他一些人这样做。

【讨论】:

  • 我认为您在验证方面是正确的。但是,添加和删除 CityViewModel 的命令是否不值得拥有自己的视图模型?
  • 他们当然可以。取决于这样做的规则是否足够通用,可以重用。
猜你喜欢
  • 2015-12-28
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
相关资源
最近更新 更多