我正在阅读一些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表单并创建新的Station实例并使用外观将其添加到存储库或某个列表的ViewModel?我的问题特别是关于异常以及如何使用绑定处理它们,而且我还要求如何在没有setter的情况下执行它,因为我读过的所有教程都使用setter。
我不想使用setter,因为逻辑上一个工作站需要有一个名称,不应该在没有名称的情况下进行实例化。
以下是我将如何解决这个问题。
导入的命名空间
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
为null / empty或者等于_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;
}
}
}