代码之家  ›  专栏  ›  技术社区  ›  Pablo

MVVM实施中的疑问

  •  2
  • Pablo  · 技术社区  · 8 年前

    这就是我实现的体系结构。

    enter image description here

    基本上,我想在视图2中选择“单元格”,“位置”将从选定的单元格填充。然后我有一个带有“系统”的组合框,我希望在系统选择时,填充不同的单元格集。为此,我使用IOC访问不同的视图模型。

    我怀疑自己是否已经按照MVVM模式实现了。带有的部件 UpdateModel 我觉得不太好。如果有人能回顾一下架构并告诉我哪些地方我可以做得更好,我将不胜感激。另外,在视图模型中有模型实例是正确的,还是应该使用数据服务模式,如mvvm-light样板中的模式?

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

    下面是代码的一些关键部分。

    视图模型2:

        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>
    

    视图模型1:

        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 回复  |  直到 8 年前
        1
  •  0
  •   ManOVision    8 年前

    这里的部分答案可以解决您对体系结构的一些代码味道和疑问:

    1. ViewModel不应该知道其他ViewModel,因此ViewModel1不应该调用ViewModel2。

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

    3. 模型可以实现INotifyPropertyChanged以及ViewModels。这样,您可以将SelectedSystem、SelectedCell和SelectedLocation的属性放在模型上,并让它们触发PropertyChanged事件。

    4. 使用ViewModel将模型从某种类型的存储库中拉出。这样,当ViewModels更新其属性时,模型的状态将保持不变。根据ViewModelLocator在内部的工作方式,ViewModel可以保持状态,也可以不保持状态。使用“模型”和/或“存储库”可确保状态持续超过ViewModel的寿命。

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