MVVM-模型与ViewModel-将代码放在哪里?

时间:2019-06-19 07:51:19

标签: c# wpf mvvm

我正在创建一个用于管理在线赛车联赛的小型应用程序。 为此,我将拥有一个数据库,该数据库可从Web访问数据并通过接口公开数据对象。该数据库尚不存在,但我创建了一个使用本地XML文件作为数据源的模型。

联赛界面的小示例:

void (*scanCompleteCB)(BLEScanResults)

现在,使用MVVM模式将其放入我的WPF中,我为数据库暴露的每个对象创建了一个模型,并在那里实现了INPC。 *注意:public interfac ISchedule { string Name { get; set; } List<IRaceSession> Races { get; } // and some more properties … IRaceSession AddRace(); void RemoveRace(IRaceSession race); // and some more Methods … } public interface IRaceSession { uint RaceId { get; } DateTime Date { get; set; } TimeSpan Duration { get; set; } // and some more properties … } ContainerModel<>是我创建的类,用于处理数据库中的更新,同时仍保持INPC不变。

ObservableModelCollection<>

然后我有一个viewModel和一个直接绑定到Model属性的视图。

public class ContainerModel<T>
{
    T Source { get; set; }

    public ContainerModel(T source)
    {
        Source = source;
    }

    void UpdateSource(T source)
    {
        // handle updates …
    }
}

public class ScheduleModel : ISchedule, ContainerModel<ISchedule>
{
    public string Name { get => Source.Name ; set { Source.Name = value; NotifyPropertyChanged(); } }

    public ObservableModelCollection<RaceSessionModel, IRaceSession> Races { get; }
    List<IRaceSession> ISchedule.Races => Source.Races

    public ScheduleModel(ISchedule source) : base(source)
    {
        Races = new ObservableModelCollection<RaceSessionModel, IRaceSession>(Source.Races);
    }

    IRaceSession AddRace()
    {
        Races.Add(// new Race Object);
    }
    void RemoveRace(IRaceSession race)
    {
        Races.Remove(// select race object to remove);
    }
}

public class RaceSessionModel : IRaceSession, ContainerModel<IRaceSession>
{
    public uint RaceId => Source.RaceId;
    puglic DateTime Date { get => Source.Date; set { Source.Date = value; NotifyPropertyChanged(); } }
    TimeSpan Duration { get => Source.Duration; set { Source.Duration = value; NotifyPropertyChanged(); } }


    //--> here come some more logic im not sure About:
    TimeSpan DurationHours 
    { 
        get => Duration.Hours;
        set 
        {
            // set only Hours componennt of Duration
            Duration = Duration
                .Subtract(Duration.Hours)
                .Add(value);
            NotifyPropertyChanged();
        }

    TimeSpan DurationMinutes 
    { 
        get => Duration.Minutes;
        set 
        {
            // set only Minutes componennt of Duration
            Duration = Duration
                .Subtract(Duration.Minutes)
                .Add(value);
            NotifyPropertyChanged();
        }
}

现在使用这种设计,我有一些担忧。我仍在摸索整个设计模式,这是我第一次从头开始构建它。

  1. 我的模型实际上并不包含数据,而只是公开数据库中的属性 我认为这实际上是viewModel应该做的事情对吗?

  2. 如您所见,我的模型还对属性Input进行了某种计算。该“业务逻辑”是否也应该放在模型之外?还是将其更好地放入ViewModel中?

毕竟,我完全怀疑我所呈现的是“模型”。称它们为ViewModels,然后将数据库中的Object用作模型,是否正确?

*编辑: 当我开始阅读时,我读到每个public class SchedulerViewModel : ViewModelBase //<-- just a Basic implementation of INPC { private ScheduleModel _schedule; public ScheduleModel Schedule { get => _schedule; set { _schedule = value; NotifyPropertyChanged(); } } public SchedulerViewModel(ScheduleModel schedule) { Schedule = schedule; } // Commands and other properties communicating with the view // … } 应该只提供一个View,这就是为什么我创建这样的类的原因。但是我不确定这是否正确。

3 个答案:

答案 0 :(得分:1)

为了将数据从模型传输到ViewModel,我将创建简单的对象(Dto-DataTransferObject),而没有(或非常少的)逻辑。 一个很好的经验法则是,您希望ViewModel中的未保存数据属于模型中的已保存数据或即将要保存的数据。

//--> here come some more logic im not sure About:
TimeSpan DurationHours 
{ 
    get => Duration.Hours;
    set 
    {
        // set only Hours componennt of Duration
        Duration = Duration
            .Subtract(Duration.Hours)
            .Add(value);
        NotifyPropertyChanged();
    }

TimeSpan DurationMinutes 
{ 
    get => Duration.Minutes;
    set 
    {
        // set only Minutes componennt of Duration
        Duration = Duration
            .Subtract(Duration.Minutes)
            .Add(value);
        NotifyPropertyChanged();
    }

我会将它们放入ViewModel中。在模型中,您需要整个Timespan对象,只有ViewModel应该知道只能在View中单独设置它们的限制。

  

当我开始阅读此书时,我会阅读您应该提供的每个视图   只有一个ViewModel,这就是为什么我这样创建类的原因。但   我不确定这是否正确。

是的,当您必须维护代码并进行仅适用于单个View的更改时,此操作以后可以省去很多麻烦。

答案 1 :(得分:1)

这可能在很大程度上取决于您要对应用程序执行的操作,但是通常我会这样处理:

  • 时间表模型
  • RaceSession的模型
  • RaceSession的ViewModel,其中包含RaceSession模型
  • 用于计划的ViewModel包含计划模型的集合 RaceSessionViewModels

从本质上讲,我一直认为模型几乎只是代表数据库中的一行。在应用程序外部独立存在的基本数据实体。那么ViewModel就是仅与应用程序相关的任何东西。

在计划模型中没有集合RaceSession模型的原因是,如果您要对RaceSession进行任何基于应用程序的操作,那便属于ViewModel,所以您d然后正在查看带有RaceSessionViewModels集合的Schedule Model。因此,我将把Models严格保持为单个数据实体,而没有内置任何类型的实体关系(联接)-这些类型的关系将内置到ViewModel层中。即使您不需要RaceSession的ViewModel,在Schedule ViewModel中仍然有RaceSession模型的集合。

作为上述示例,我相信AddRace方法确实属于Schedule ViewModel,而不是Schedule Model。

关于TimeSpan的计算,我可能将Hours and Minutes作为get的唯一属性(在RaceSession ViewModel上),并在RaceSessionViewModel上使用其他方法来更改{{1 }}属性。具体的实现取决于更新时是否在数据库中实际更改它们。

一些伪代码示例

Duration

答案 2 :(得分:0)

  1. 不。视图模型将数据(模型而不是数据库)与视图连接。但是它既不操纵视图也不操纵数据库。
  2. 我不会将其留在模型中。这种东西实际上属于视图模型。 在每个视图中,都可以显示多个视图模型,但是您肯定至少需要一个视图模型。 我建议,当您已经开始构建MVVM时,现在您应该在Internet上某个实现该设计模式的示例中进行查找。我想您已经阅读了一些背后的理论。