【发布时间】:2021-03-02 17:20:58
【问题描述】:
我正在创建一个用于管理在线赛车联赛的小型应用程序。 为此,我将拥有一个从 Web 访问数据并通过接口公开数据对象的数据库。该数据库尚不存在,但我创建了一个使用本地 XML 文件作为数据源的 Mockup。
联赛界面的小例子:
public interface 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 …
}
现在,为了使用 MVVM 模式将其放入我的 WPF 中,我为数据库公开的每个对象创建了一个模型,并在那里实现了 INPC。
*注意:ContainerModel<> 和 ObservableModelCollection<> 是我创建的类,用于处理来自数据库的更新,同时仍保持 INPC 完整。
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();
}
}
然后我有一个 viewModel 和一个直接绑定到 Model 属性的视图。
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
// …
}
现在有了这个设计,我有一些担忧。我仍在摸索整个设计模式,这是我第一次从头开始构建它。
-
我的模型并不真正包含数据,而只是公开数据库中的属性 我是否认为这实际上是 viewModel 应该做的事情?
-
如您所见,我的模型还对属性输入进行了某种计算。这种“业务逻辑”也应该放在模型之外吗?还是将其放入 ViewModel 中会更好?
毕竟我怀疑我所呈现的是“模型”。将它们称为 ViewModel,然后将数据库中的 Object 作为模型进行操作是否正确?
*编辑:
当我从这个开始时,我读到对于每个View,你应该只提供一个ViewModel,这就是我创建这样的类的原因。但是我不确定这是否正确。
【问题讨论】:
-
在这种情况下,您也可以保持简单:将 IRaceSession 和 ISchedule 视为模型,其他所有内容(实际上并不多)都放在 ViewModel 中。我不明白你为什么会为了它而在两者之间添加一个额外的层(实际上什么都不做)。
-
@stijn:谢谢。这基本上就是我的问题要解决的问题,但我担心当应用程序最终变得更加复杂时,这种方法是否会反击。
-
可能,但是您以后总是可以重构,而且很容易做到。请参阅 KISS 和 YAGNI 原则:如果简单、干净、可读的代码现在可以完成这项工作,那么在我看来,您必须有 非常 充分的理由不使用它。我已经编写了相当多的 MVVM 代码并回顾过去,试图严格遵守 MVVM 或不承认模型是什么(或严格遵守“模型”的一个定义),通常只是数据的表示,导致过于复杂。