我正在尝试制作一个简单的表单,将数据添加到数据库中,如果数据有效,则清除/重置文本框和其他控件。目前,我使用 RelayCommand 将所有数据从控件发送到我的视图模型,在视图模型中验证数据并将其添加到数据库中。
我遇到的问题是,一旦它进入数据库,我需要再次与页面交互并清除文本框,但使用我当前的方法(没有2)我无法做到这一点。
不久前,我从 Win Forms 迁移到 WinUi 3,从那时起,我一直在努力适应 MVVM 的做事方式。当谈到这个问题时,根据我的研究,WinUi 3 中似乎有几种处理数据输入的方法。
第一个就像在 WinForms 中单击按钮和文件后面的代码,第二个使用 RelayCommands 是我目前正在做的事情,第三个方法是我在另一个问题中看到建议的。
将第二个和第三个选项结合起来是最好的方法吗?即为每个控件添加单独的字段,然后使用按钮命令调用 RelayCommand 将其全部链接在一起?
<Button Content="Add" Click="AddSupplier" />
<Button x:Name="AddSupplierBtn" Content="Add Supplier" Grid.Row="4" Grid.Column="1"
Command="{x:Bind ViewModel.AddSupplierCommand}"
CommandParameter="{x:Bind ViewModel.CreateSupplier(NameTextBox.Text, AddressTextBox.Text, PhoneNumberTextBox.Text, WebsiteTextBox.Text), Mode=OneWay}"/>
<TextBox x:Name="messageBox" Text="{Binding TextBoxInput, Mode=TwoWay}">
public string TextBoxInput
{
get { return _textBoxInput; }
set
{
_textBoxInput = value;
OnPropertyChanged(nameof(TextBoxInput));
}
}
private string _textBoxInput;
目前我自己的代码如下:
供应商页面
<Grid Loaded="OnRootGridLoaded">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Name" Grid.Row="0" Grid.Column="0" />
<TextBox x:Name="NameTextBox" Grid.Row="0" Grid.Column="1" />
<TextBlock Text="Address (Optional)" Grid.Row="1" Grid.Column="0" />
<TextBox x:Name="AddressTextBox" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="PhoneNumber (Optional)" Grid.Row="2" Grid.Column="0" />
<TextBox x:Name="PhoneNumberTextBox" Grid.Row="2" Grid.Column="1"/>
<TextBlock Text="Website" Grid.Row="3" Grid.Column="0" />
<TextBox x:Name="WebsiteTextBox" Grid.Row="3" Grid.Column="1"/>
<Button x:Name="AddSupplierBtn" Content="Add Supplier" Grid.Row="4" Grid.Column="1"
Command="{x:Bind ViewModel.AddSupplierCommand}"
CommandParameter="{x:Bind ViewModel.CreateSupplier(NameTextBox.Text, AddressTextBox.Text, PhoneNumberTextBox.Text, WebsiteTextBox.Text), Mode=OneWay}"/>
</Grid>
查看模型
public partial class SupplierViewModel: ObservableObject
{
RecipeDBContext context;
[ObservableProperty]
private ObservableCollection<Supplier> _suppliers;
public SupplierViewModel()
{
context = new RecipeDBContext();
_suppliers = new ObservableCollection<Supplier>();
UpdateSuppliers(context.Suppliers.ToList());
_suppliers.CollectionChanged += this.OnCollectionChanged;
}
public void UpdateSuppliers(List<Supplier> suppliers)
{
Suppliers.Clear();
foreach (Supplier supplier in suppliers)
{
Suppliers.Add(supplier);
}
}
public Supplier CreateSupplier(string name, string address, string phoneNumber, string website) => new(name, address, phoneNumber, website);
[RelayCommand]
private void AddSupplier(Supplier supplier)
{
if (supplier != null)
{
Suppliers.Add(supplier);
}
else
{
}
}
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Supplier newItem in e.NewItems)
{
context.Suppliers.Add(newItem);
}
}
if (e.OldItems != null)
{
foreach (Supplier oldItem in e.OldItems)
{
context.Suppliers.Remove(oldItem);
}
}
context.SaveChanges();
}
}
型号
public partial class Supplier: ObservableObject
{
public int Id { get; set; }
[ObservableProperty]
private string _name;
[ObservableProperty]
private string _address;
[ObservableProperty]
private string _phoneNumber;
[ObservableProperty]
private string _website;
public Supplier(string name, string address, string phoneNumber, string website)
{
Name= name;
Address= address;
PhoneNumber= phoneNumber;
Website= website;
}
}
Xaml 将文本框绑定到字段
<TextBox x:Name="AddressTextBox" Header="Address (Optional)" PlaceholderText="Enter Address" PlaceholderForeground="Gray" Text="{x:Bind Supplier.Address, Mode=TwoWay}" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
型号
public partial class Supplier: ObservableValidator
{
public int Id { get; set; }
[ObservableProperty]
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Name is Required")]
[MinLength(2, ErrorMessage = "Name should be longer than one character")]
private string _name = string.Empty;
[ObservableProperty]
private string _address = string.Empty;
[ObservableProperty]
[EmailAddress]
private string _email = string.Empty;
[ObservableProperty]
[Phone]
private string _phoneNumber = string.Empty;
[ObservableProperty]
[Url]
private string _website = string.Empty;
public Supplier()
{
this.ErrorsChanged += Supplier_ErrorsChanged;
this.PropertyChanged += Supplier_PropertyChanged;
SetProperty(ref _name, _name, true, nameof(Name));
}
~Supplier()
{
ErrorsChanged -= Supplier_ErrorsChanged;
PropertyChanged -= Supplier_PropertyChanged;
}
public Supplier(string name, string address, string email, string phoneNumber, string website)
{
Name= name;
Address= address;
Email= email;
PhoneNumber= phoneNumber;
Website= website;
}
public string Errors => string.Join(Environment.NewLine, from ValidationResult e in GetErrors(null) select e.ErrorMessage);
public void RemoveErrors()
{
ClearErrors();
}
private void Supplier_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(HasErrors))
{
OnPropertyChanged(nameof(HasErrors)); // Update HasErrors on every change, so I can bind to it.
}
}
private void Supplier_ErrorsChanged(object sender, System.ComponentModel.DataErrorsChangedEventArgs e)
{
OnPropertyChanged(nameof(Errors)); // Update Errors on every Error change, so I can bind to it.
}
}
视图模型代码:
public partial class SupplierViewModel: ObservableValidator
{
RecipeDBContext context;
private Supplier _supplier = new Supplier();
public Supplier Supplier => _supplier;
[ObservableProperty]
private ObservableCollection<Supplier> _suppliers;
public SupplierViewModel()
{
context = new RecipeDBContext();
_suppliers = new ObservableCollection<Supplier>();
UpdateSuppliers(context.Suppliers.ToList());
_suppliers.CollectionChanged += this.OnCollectionChanged;
}
[RelayCommand]
private void AddSupplier(Supplier supplier)
{
if (supplier != null)
{
if (!supplier.HasErrors)
{
Supplier s = new Supplier()
{
Name= supplier.Name,
Address= supplier.Address,
PhoneNumber= supplier.PhoneNumber,
Website= supplier.Website,
};
Suppliers.Add(s);
supplier.Name = string.Empty;
supplier.RemoveErrors();
}
else
{
Debug.WriteLine("Errors\n" + supplier.Errors);
}
}
}
}