对MVVM实现的怀疑

时间:2016-05-08 19:10:40

标签: c# wpf mvvm-light

这是我实施的架构。

enter image description here

基本上我想在视图2中选择“单元格”,并且将从所选单元格中填充“位置”。然后我有“系统”的组合框,我想要系统选择,以填充不同的单元格集。为此,我使用IOC访问不同的视图模型。

怀疑是我是否已根据MVVM模式实现。 UpdateModel的部分对我来说不太好看。如果有人可以审查架构并告诉我我可以做得更好,我将不胜感激。在视图模型中使用模型实例也是正确的,或者我应该使用数据服务模式,就像在mvvm-light样板中一样?

问题:我是否可以在不调用UpdateModel函数的情况下实现对系统更改的响应,但使用mvvm-light的本机机制来更新ViewModel2?

代码的一些关键部分。

ViewModel2:

    public List<string> LocationList
    {
        get
        {
            var cells = _wList.GetCells(currentSystemNumber);
            var cell = cells[_selectedCellItem.Key];
            return cell.Locations;
        }
    }

    private KeyValuePair<int, string> _selectedCellItem;
    public KeyValuePair<int, string> SelectedCellItem
    {
        get
        {
            return _selectedCellItem;
        }

        set
        {
            Set(ref _selectedCellItem, value);
            RaisePropertyChanged("LocationList");
        }
    }

    public ObservableCollection<KeyValuePair<int, string>> CellList
    {
        get
        {
            int count = _wList.GetCells(currentSystemNumber).Count;
            ObservableCollection<KeyValuePair<int, string>> cells = new ObservableCollection<KeyValuePair<int, string>>();
            for(int i = 0; i < count; i++)
                cells.Add(new KeyValuePair<int, string>(i, string.Format("Cell {0}/{1}", i, currentSystemNumber+1)));
            return cells;
        }
    }

    public void UpdateModel(int system)
    {
        currentSystemNumber = system;

        RaisePropertyChanged("CellList");
        RaisePropertyChanged("LocationList");
    }

视图2:

<Grid>
    <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="104" Margin="121,32,0,0" VerticalAlignment="Top" Width="144" ItemsSource="{Binding LocationList}"/>
    <ListBox x:Name="listBox1" HorizontalAlignment="Left" Height="104" Margin="10,32,0,0" VerticalAlignment="Top" Width="102" ItemsSource="{Binding CellList}" SelectedItem="{Binding SelectedCellItem}" DisplayMemberPath="Value"/>
    <Label x:Name="label" Content="Cells" HorizontalAlignment="Left" Margin="10,1,0,0" VerticalAlignment="Top"/>
    <Label x:Name="label1" Content="Locations" HorizontalAlignment="Left" Margin="121,1,0,0" VerticalAlignment="Top"/>
</Grid>

ViewModel1:

    private ObservableCollection<KeyValuePair<int, string>> _systems = new ObservableCollection<KeyValuePair<int, string>>();
    public ObservableCollection<KeyValuePair<int, string>> Systems
    {
        get
        {
            return _systems;
        }
    }

    private KeyValuePair<int, string> _selectedSystemItem;
    public KeyValuePair<int, string> SelectedSystemItem
    {
        get
        {
            return _selectedSystemItem;
        }
        set
        {
            Set(ref _selectedSystemItem, value);
            var locator = (ViewModelLocator)Application.Current.Resources["Locator"];
            var vm = locator.DASrvPageVM;
            vm.UpdateModel(value.Key);
        }
    }

1 个答案:

答案 0 :(得分:0)

这里的部分答案是为了解决您的架构中的一些代码气味和疑问:

  1. ViewModels不应该了解其他ViewModel,因此ViewModel1不应该调用ViewModel2。

  2. 如果可能的话,不应该使用ServiceLocator。 ViewModelLocator只应由框架使用,不能直接调用。如果您修复问题1,那么也会删除此问题。

  3. 模型可以实现INotifyPropertyChanged以及ViewModel。这样,您可以在模型上放置SelectedSystem,SelectedCell和SelectedLocation的属性,并激活PropertyChanged事件。

  4. 使用ViewModel从某种类型的存储库中提取模型。这样,当ViewModel更新其属性时,模型的状态将保持不变。 ViewModel可能会也可能不会根据ViewModelLocator在内部的工作方式保持状态。使用模型和/或存储库可确保状态持续超出ViewModel的生命周期。

  5. 对ViewModel和Models中的几乎所有集合类型使用ObservableCollections,以便Views可以绑定到这些集合类型,而无需在getter上执行如此多的逻辑。经验法则,如果您想在View上查看任何值或集合,请确保它们是Observable。这将允许使用MVVM绑定的全部功能,并删除大量试图保持View更新的样板代码。