在 MVVM Community Toolkit VM 中我加载了一个 Person(带有 20 个可观察的 props),在 VI 中我显示了 Person 的数据。如何在任何数据更改时启用“保存按钮”?

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

我有模型

public partial class Patient : GenericEntity
{
    [ObservableProperty]
    private int genderId;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Crucials))]
    private string lastName = string.Empty;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Crucials))]
    private string firstName = string.Empty;

    [ObservableProperty]
    private string fatherName = string.Empty;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Crucials))]
    [NotifyPropertyChangedFor(nameof(Age))]
    private DateTime _DOB = DateTime.Now;

    [NotMapped]
    public int Age
    {
        get
        {
            //DateOnly currentDate = DateOnly.FromDateTime(DateTime.Now);
            DateTime currentDate =DateTime.Now;
            int age = currentDate.Year - DOB.Year;

            // Check if the current date is before the birth date
            if (currentDate < DOB.AddYears(age))
            {
                age--;
            }

            return age;
        }
    }

    [ObservableProperty]
    private string _address = "";
    [ObservableProperty]
    private string _city = "";
    [ObservableProperty]
    private string _country = "";
    [ObservableProperty]
    private string _tel1 = "";
    [ObservableProperty]
    private string _tel2 = "";
    [ObservableProperty]
    private string _email = "";
  
   //(15 more fields are following all of them decorated with [ObservableProperty])
}

视图模型如下

公共部分类 PatientViewModel : ObservableObject { 私人布尔_patentPropertyChanged = false;

private AppDbContext _db;

private readonly PatientRepository _patientRepository;
private readonly NATreeNodeRepository _natreenodeRepository;

private Patient? patient;

[ObservableProperty]
private int _patientId = 0;

[RelayCommand(CanExecute = nameof(CanSaveChanges), IncludeCancelCommand = true)]
private async Task SaveChanges(CancellationToken token)
{
    var hasChanges = _db.ChangeTracker.HasChanges();
    if (hasChanges)
    {
        try
        {
            // Update the Patient's registration date to DateTime.Now
            if (Patient != null)
            {
                Patient.UpdatedOn = DateTime.Now;
            }

            await _db.SaveChangesAsync();
            MessageBox.Show("Changes successfully saved to the database!");
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    MessageBox.Show("Saved changes");
}

}

private bool CanSaveChanges() => PatientPropertyChanged;



public PatientViewModel(int patientId)
{
    _db = new();

    _patientRepository = new PatientRepository(_db);
    _natreenodeRepository = new NATreeNodeRepository(_db);

    PatientId = patientId;

    InitializeAsync(PatientId);

    _patientPropertyChanged = false;
}

private async void InitializeAsync(int patientId)
{
    try
    {
                                                                                        // Retrieve the patient with the given ID from the repository
        Patient = await Task.Run(() => _patientRepository.Get(patientId)); // Replace with your repository method

        // Check if patient is null or doesn't exist
        if (Patient == null)
        {
            Patient = new()
            {
            };
            _patientRepository.Add(Patient);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Error: " + ex.Message);
    }
}

}

PersonView 窗口包含多个控件(一个用于每个人的属性)和一个最初禁用的 SaveButton,该按钮绑定到 RelayCommand SaveCommand

我的问题是,当用户在此窗口上更改任何人的属性时,如何启用或禁用保存按钮。

由于我陷入困境,我找不到这个问题的任何解决方案。

如果 Person 包含 2-3 个属性,有一个解决方案。但是当它包含很多时,我就无法想出一个聪明的解决方案来避免重复代码块

提前致谢

wpf data-binding windows-community-toolkit relaycommand canexecute
2个回答
0
投票

解决方案 1 - 使用数据库

据我了解您数据库的功能,您可以将其委托给您的数据库,因为

_db.ChangeTracker.HasChanges()
接缝检查是否有更改。所以你可以将
CanSaveChanges()
更改为

private bool CanSaveChanges() => _db.ChangeTracker.HasChanges();

解决方案 2 - 使用 PropertyChanged 事件

否则,如果您的数据库无法检查更改,您可以使用 PropertyChanged 事件,例如:

// Properties for Patient and Changed State
[ObservableProperty] private bool _patientPropertyChanged;
[ObservableProperty] private Patient _patient;

public bool CanSaveChanges() => PatientPropertyChanged;

private async void InitializeAsync(int patientId)
{
    try
    {
         if (Patient == null)
        {
            Patient = new()
            {
            };
            _patientRepository.Add(Patient);
        }

        //Add Event Handle to set changed
        Patient.PropertyChanged += (s, e) => 
        {
            //You may filter here for relevant changes
            PatientPropertyChanged = true;
        };
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Error: " + ex.Message);
    }
}

[RelayCommand(CanExecute = nameof(CanSaveChanges), IncludeCancelCommand = true)]
private async Task SaveChanges(CancellationToken token)
{
    var hasChanges = _db.ChangeTracker.HasChanges();
    if (hasChanges)
    {
        //..
    }
    //Reset changed Satte
    PatientPropertyChanged = false;
}

0
投票

每当设置

CanExecuteChanged
属性时,您都应该引发该命令的
PatientPropertyChanged
事件。

在 MVVM 工具包中,您可以通过将

[NotifyCanExecuteChangedFor]
属性应用于属性的支持字段来完成此操作:

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(SaveChangesCommand))]
private bool _patientPropertyChanged;
© www.soinside.com 2019 - 2024. All rights reserved.