数据输入+数据输入后清除控件

问题描述 投票:0回答:1

我正在尝试制作一个简单的表单,将数据添加到数据库中,如果数据有效,则清除/重置文本框和其他控件。目前,我使用 RelayCommand 将所有数据从控件发送到我的视图模型,在视图模型中验证数据并将其添加到数据库中。

我遇到的问题是,一旦它进入数据库,我需要再次与页面交互并清除文本框,但使用我当前的方法(没有2)我无法做到这一点。

不久前,我从 Win Forms 迁移到 WinUi 3,从那时起,我一直在努力适应 MVVM 的做事方式。当谈到这个问题时,根据我的研究,WinUi 3 中似乎有几种处理数据输入的方法。

第一个就像在 WinForms 中单击按钮和文件后面的代码,第二个使用 RelayCommands 是我目前正在做的事情,第三个方法是我在另一个问题中看到建议的。

将第二个和第三个选项结合起来是最好的方法吗?即为每个控件添加单独的字段,然后使用按钮命令调用 RelayCommand 将其全部链接在一起?

  1. 单击时
<Button Content="Add" Click="AddSupplier" />
  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}"/>

  1. 将控件绑定到字段并在类中完成这一切 示例取自此处: 命令触发后如何使用 MVVM 清除文本框
<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 user-interface entity-framework-core winui-3 community-toolkit-mvvm
1个回答
0
投票

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);
        }
    }
}
}
© www.soinside.com 2019 - 2024. All rights reserved.