我正在阅读一些ViewModel教程,并试图在创建“ Station”对象的窗口中实现它。我的模型站如下:
using System;
namespace Model
{
public class Station
{
public string Name { get; }
public Station(string name)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Station cannot have no name.");
Name = name;
}
}
}
一个人如何创建一个绑定到WPF表单的ViewModel并创建一个新的Station实例,并使用外观将其添加到存储库或某个列表中?我的问题特别是关于异常以及如何通过绑定处理异常的问题,我还问如何在不使用设置方法的情况下进行操作,因为我阅读的所有教程都使用了设置方法。
我不想使用setter,因为从逻辑上讲,一个工作站必须有一个名称,并且没有名称就不能被实例化。
答案 0 :(得分:1)
这是我要解决的方法。
导入的名称空间
using System;
using System.Windows.Input;
using System.Threading.Tasks;
using ReactiveUI; // nuget package reactiveui
模型
namespace Models
{
public class Station
{
public Station(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("message", nameof(name));
}
Name = name;
}
public string Name { get; }
}
}
服务
namespace Services
{
public interface IStationService
{
Task CreateAsync(Models.Station model);
Task UpdateAsync(Models.Station oldModel, Models.Station newModel);
}
}
ViewModels.Base
namespace ViewModels.Base
{
public class ViewModelBase : ReactiveObject
{
public virtual Task InitializeAsync(object parameter)
{
return Task.CompletedTask;
}
}
}
ViewModels
如果Name
为空/空或等于_originalModel
中的名称,则可以扩展此示例并“禁用”命令,以防止执行save命令时发生异常。
或者您可以在SaveCommandExecuteAsync
中捕获异常。
要点是:我仅在要保存新模型实例时创建它。
namespace ViewModels
{
public class StationEditViewModel : Base.ViewModelBase
{
public StationEditViewModel(Services.IStationService stationService)
{
StationService = stationService ?? throw new ArgumentNullException(nameof(stationService));
}
protected Services.IStationService StationService { get; }
string _name;
public string Name { get => _name; set => this.RaiseAndSetIfChanged(ref _name, value); }
public ICommand SaveCommand => ReactiveCommand.CreateFromTask(SaveCommandExecuteAsync);
private async Task SaveCommandExecuteAsync()
{
var oldModel = _originalModel;
var newModel = await SaveToModelAsync();
if (oldModel == null)
await StationService.CreateAsync(newModel);
else
await StationService.UpdateAsync(oldModel, newModel);
await LoadFromModelAsync(newModel);
}
public override Task InitializeAsync(object parameter)
{
return LoadFromModelAsync(parameter as Models.Station);
}
Models.Station _originalModel;
private Task LoadFromModelAsync(Models.Station model)
{
_originalModel = model;
Name = model?.Name;
return Task.CompletedTask;
}
private Task<Models.Station> SaveToModelAsync()
{
var model = new Models.Station(Name);
return Task.FromResult(model);
}
}
}
控制台应用程序中的最终测试
namespace so53567553
{
using Models;
class Program
{
static async Task Main(string[] args)
{
var service = new TestStationService();
var vm = new ViewModels.StationEditViewModel(service);
vm.PropertyChanged += (s, e) => Console.WriteLine($"PropertyChanged '{e.PropertyName}'");
// we will work on a new Station
Console.WriteLine("* Create Station");
await vm.InitializeAsync(null);
vm.Name = "New Station";
vm.SaveCommand.Execute(null);
// we will work on an existing Station
Console.WriteLine("* Edit Station");
await vm.InitializeAsync(new Station("Paddington"));
vm.Name = "London";
vm.SaveCommand.Execute(null);
}
}
class TestStationService : Services.IStationService
{
public Task CreateAsync(Station model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
Console.WriteLine($"Create Station '{model.Name}'");
return Task.CompletedTask;
}
public Task UpdateAsync(Station oldModel, Station newModel)
{
if (oldModel == null)
{
throw new ArgumentNullException(nameof(oldModel));
}
if (newModel == null)
{
throw new ArgumentNullException(nameof(newModel));
}
Console.WriteLine($"Update Station from '{oldModel.Name}' to '{newModel.Name}'");
return Task.CompletedTask;
}
}
}