【发布时间】:2021-06-03 13:29:13
【问题描述】:
我终于放弃并开始在我的 EFCore 项目中学习和应用 MVVM 架构。但是,我还不明白范围服务是如何工作的。在我之前的问题中,有人告诉我,我需要为每个视图模型使用一个范围,否则,因为我正在使用异步方法,我将在同一个 DbContext 上获得并发事务(这是不允许的)。
我还在这里读到,在仍然遵循 MVVM 的同时使用对话窗口的一种方法是拥有一个服务,该服务将创建一个具有动态填充视图模型的对话窗口容器。
到目前为止,一切都很好。但是我遇到了一个障碍: 我在我的 MainView 上,我运行一个打开一个新对话框窗口的命令(我认为是一个新的范围)。在 that 对话框中,我运行了一个应该打开 another 对话框窗口的命令。但是,当试图关闭时,我设法关闭了父对话框而不是焦点窗口。我的相关代码如下:
我在这里做错了什么?
PS.:为了更好的可读性,我将名称翻译成英文,但我可能会漏掉一个或另一个 - 如果我能解决任何问题,请告诉我。
public class PurchasesViewModel : ViewModelBase
{
private readonly IDialogGenerator _purchaseDialogGenerator;
private readonly IDialogViewModelFactory _purchaseRecordVMFactory;
public ICommand CreateNewPurchase { get; set; }
public PurchasesViewModel(IServiceProvider services, IDialogGenerator purchaseVMDialogGenerator)
{
_purchaseDialogGenerator = purchaseVMDialogGenerator;
IServiceScope purchaseVMScope = services.CreateScope();
IServiceProvider provider = purchaseVMScope.ServiceProvider;
_purchaseRecordVMFactory = provider.GetRequiredService<IDialogViewModelFactory>();
CreateNewPurchase = new CreatePurchaseCommand(_purchaseDialogGenerator, _purchaseRecordVMFactory);
}
}
internal class CreatePurchaseCommand : ICommand
{
private IDialogGenerator _purchaseDialogGenerator;
private IDialogViewModelFactory _purchaseVMFactory;
public CreatePurchaseCommand(IDialogGenerator PurchaseRecordDialogGenerator, IDialogViewModelFactory PurchaseRecordVMFactory)
{
_purchaseDialogGenerator = PurchaseRecordDialogGenerator;
_purchaseVMFactory = PurchaseRecordVMFactory;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_purchaseDialogGenerator.ShownViewModel = _purchaseVMFactory.CreateDialogContentViewModel(DialogType.RecordPurchases);
_purchaseDialogGenerator.ShowDialog();
}
}
public class PurchaseRecordViewModel : DialogContentViewModelBase
{
private readonly IMessaging<PURCHASE> _purchaseMessaging;
private readonly IDialogGenerator _purchaseDialogGenerator;
private readonly IDialogGenerator _importViaXMLDialogGenerator;
private readonly IDialogViewModelFactory _importViaXMLVMFactory;
public ICommand SavePurchase { get; set; }
public ICommand ImportXML { get; set; }
public PurchaseRecordViewModel(IServiceProvider servicos, IDialogGenerator PurchaseRecordDialogGenerator)
{
_purchaseDialogGenerator = PurchaseRecordDialogGenerator;
IServiceScope scope = servicos.CreateScope();
IServiceProvider provider = scope.ServiceProvider;
_importViaXMLDialogGenerator = provider.GetRequiredService<IDialogGenerator>();
_importViaXMLVMFactory = provider.GetRequiredService<IDialogViewModelFactory>();
_purchaseMessaging = provider.GetRequiredService<IMessaging<PURCHASE>>();
SavePurchase = new SalvaPurchaseCommandAsync(PurchaseRecordDialogGenerator);
ImportXML = new ImportXMLDePurchaseCommand(_importViaXMLDialogGenerator, _importViaXMLVMFactory);
}
}
internal class ImportXMLFromPurchaseCommand : ICommand
{
private readonly IDialogGenerator _importviaXMLDialogGenerator;
private readonly IDialogViewModelFactory _importXMLVMFactory;
public ImportXMLFromPurchaseCommand(
IDialogGenerator importviaXMLDialogGenerator,
IDialogViewModelFactory importXMLVMFactory)
{
_importviaXMLDialogGenerator = importviaXMLDialogGenerator;
_importXMLVMFactory = importXMLVMFactory;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_importviaXMLDialogGenerator.ShownViewModel = _importXMLVMFactory.CreateDialogContentViewModel(DialogType.ImportXML);
_importviaXMLDialogGenerator.ShowDialog();
}
}
internal class SalvaPurchaseCommandAsync : ICommand
{
private readonly IDialogGenerator _dialogGenerator;
public SalvaPurchaseCommandAsync(IDialogGenerator dialogGenerator)
{
_dialogGenerator = dialogGenerator;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_dialogGenerator.Result = DialogResult.OK;
_dialogGenerator.Close();
}
}
public class ImportViaXMLViewModel : DialogContentViewModelBase
{
public ICommand ImportArquivoXML { get; set; }
public ICommand Import { get; set; }
private readonly IDialogGenerator _importViaXMLDialogGenerator;
public ImportViaXMLViewModel(IMessaging<PURCHASE> messaging,
IDialogGenerator importViaXMLDialogGenerator)
{
_importViaXMLDialogGenerator = importViaXMLDialogGenerator;
Import = new ImportCommand(this, messaging, _importViaXMLDialogGenerator);
}
}
internal class ImportCommand : ICommand
{
private readonly IMessaging<PURCHASE> _messaging;
private readonly IDialogGenerator _dialogGenerator;
public ImportCommand(IMessaging<PURCHASE> messaging, IDialogGenerator dialogGenerator)
{
_messaging = messaging;
_dialogGenerator = dialogGenerator;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_messaging.Message = new COMPRA();
_dialogGenerator.Result = DialogResult.OK;
_dialogGenerator.Close();
}
}
public abstract class AsyncCommandBase : ICommand
{
private bool _isExecuting;
private readonly Action<Exception> _onException;
public bool IsExecuting
{
get { return _isExecuting; }
set {
_isExecuting = value;
CanExecuteChanged?.Invoke(this, new EventArgs());
}
}
public AsyncCommandBase(Action<Exception> onException)
{
this._onException = onException;
}
public virtual event EventHandler CanExecuteChanged;
public virtual bool CanExecute(object parameter)
{
return !IsExecuting;
}
public async void Execute(object parameter)
{
IsExecuting = true;
try
{
await ExecuteAsync(parameter);
}
catch (Exception ex)
{
_onException(ex);
}
IsExecuting = false;
}
protected abstract Task ExecuteAsync(object parameter);
}
【问题讨论】:
标签: c# mvvm dependency-injection entity-framework-core