c# - 带有 EF Core 的 MVVM - 作为命令参数的新实体,在视图模型中具有绑定属性
问题描述
在进一步研究了 Xamarin.Forms 中的 MVVM 模式后,我将所有 ViewModel 函数包装到命令中,并在我的页面中从 XAML 调用它们。此外,我想通过我的命令确保可测试性,因此我将依赖项作为命令参数传递。
我有一个页面,可以在其中创建一个新实体并将其添加到 ef 核心数据库。
在用户将所有需要的值填写到组件中并因此设置 ViewModel 属性并单击页面的按钮后,应将实体添加到数据库中。
我的代码代表所描述的行为:
约会视图模型.cs:
public class AppointmentViewModel : INotifyPropertyChanged
{
// Bound properties
public string Title { get; set; }
public DateTime Date { get; set; }
// Command to add new appointment
public ICommand AddAppointmentCommand { get; }
// The appointment entity which will be passed as a command parameter
public Appointment BoundAppointment => new Appointment(Title, Date);
AppointmentViewModel()
{
AddAppointmentCommand = new Command<Appointment>(async a => await AddAppointment(a));
}
public async Task AddAppointment(Appointment appointment)
{
// Code to add an appointment to the database through Entity Framework core
}
}
约会页面.xaml:
<Button Command="{Binding AddAppointmentCommand}" CommandParameter="{Binding BoundAppointment}"/>
我目前面临的问题是该属性BoundAppointment
仅在打开页面时才被初始化,因此用户没有提供任何值。
因此,当执行命令时,创建的实体没有用户提供的值。(标题和日期仍然有它们的默认值)
我想将我的实体作为命令参数传递,但要使用所有提供的值。遗憾的是我没有找到解决方案,这可以确保我的命令的可测试性,例如。在单元测试中。
解决方案
因此,当执行命令时,创建的实体没有用户提供的值。(标题和日期仍然有它们的默认值)
从您的代码中,您已经实现了 INotifyPropertyChanged,但您没有实现 viewmodel 的每个属性的所有设置器规则。您可以尝试根据以下代码修改您的代码。
public class AppointmentViewModel : INotifyPropertyChanged
{
// Bound properties
private string _Title;
public string Title
{
get { return _Title; }
set
{
_Title = value;
RaisePropertyChanged("Title");
}
}
private DateTime _Date;
public DateTime Date
{
get { return _Date; }
set
{
_Date = value;
RaisePropertyChanged("Date");
}
}
// Command to add new appointment
public ICommand AddAppointmentCommand { get; }
// The appointment entity which will be passed as a command parameter
private Appointment _BoundAppointment;
public Appointment BoundAppointment
{
get { return _BoundAppointment; }
set
{
_BoundAppointment = new Appointment(Title, Date);
RaisePropertyChanged("BoundAppointment");
}
}
AppointmentViewModel()
{
AddAppointmentCommand = new Command<Appointment>(async a => await AddAppointment(a));
}
public async Task AddAppointment(Appointment appointment)
{
// Code to add an appointment to the database through Entity Framework core
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
更新:
当 Title 和 Date 值改变时,你可以更新BoundAppointment
private string _Title;
public string Title
{
get { return _Title; }
set
{
_Title = value;
RaisePropertyChanged("Title");
BoundAppointment = new Appointment(Title, Date);
}
}
private DateTime _Date;
public DateTime Date
{
get { return _Date; }
set
{
_Date = value;
RaisePropertyChanged("Date");
BoundAppointment = new Appointment(Title, Date);
}
}
推荐阅读
- react-native - 如何为 ui-kitten 的卡片标题提供道具
- docker - 如何在 Hyper-V 上以编程方式启用“在没有 TLS 的 tcp://localhost:2375 上公开守护程序”(Windows 10 v2004)
- react-native - 在 react-native-video 中,视频播放完毕后如何重置视频播放器?
- javascript - Javascript秒表!秒表从 1 小时开始
- google-chrome - 安装 chronium 时出错:软件包包含不满足的依赖项:libc6-dev: Break: libgcc-8-dev (<8.4.0-2 ~) 但必须安装 8.3.0-6
- python-3.x - 我的 cplex 逻辑约束不能正常工作
- c++ - 有没有比在所有派生类都没有实现的基础上添加新的虚函数更好的设计实践
- javascript - Vue.js + TS 对象在文件输入时可能为“空”
- android - Android 中的可见性消失
- office365 - 将本地文件保存到 MS 团队