c# - 带有所有者的 MVVM showDialog 并在后台工作人员完成时关闭

标签 c# wpf mvvm

我只是想掌握 WPF 中的 MVVM 模式(目前没有任何框架)。

场景:

我有一个主窗口,单击“开始工作”按钮,该按钮绑定(bind)到 View 模型中的某个命令。进度对话框应该打开“取消”按钮,它应该显示在所有者窗口的中心(所以我需要传递所有者),我按下取消并在后台工作人员上调用“CancelAsync”方法。

MVVM 的原则是 View 模型永远不应该知道关于 View 的任何信息,在我的情况下,我违反了这条规则。

代码隐藏(无 MVVM)解决方案:

主窗口部分:

private void Button_Click(object sender, RoutedEventArgs e)
{
    backgroundWorker.RunWorkerAsync();

    progressWindow = new ProgressWindow(backgroundWorker);
    progressWindow.Owner = this;
    progressWindow.ShowDialog();
}

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    progressWindow.Close();
}

进度窗口部分:
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
    backgroundWorker.CancelAsync();
}

我尝试将此代码转换为 MVVM(这是错误的)
public class MainViewModel
{
    public ICommand DoSomething { get; }
    private BackgroundWorker backgroundWorker;

    private PleaseWaitView pleaseWaitView;

    public MainViewModel()
    {
        backgroundWorker = new BackgroundWorker() { WorkerSupportsCancellation = true };
        backgroundWorker.DoWork += BackgroundWorker_DoWork;
        backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;

        var pleaseWaitViewModel = new PleaseWaitViewModel(backgroundWorker);
        pleaseWaitView = new PleaseWaitView();
        pleaseWaitView.Owner = Application.Current.MainWindow;
        pleaseWaitView.DataContext = pleaseWaitViewModel;

        DoSomething = new ActionCommand<object>(DoSomethingImpl);
    }

    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        pleaseWaitView.Close();
    }

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Some work
        Thread.Sleep(5000);
    }

    private void DoSomethingImpl(object parameter)
    {
        pleaseWaitView.ShowDialog();
    }
}

如何解决这个问题?我在 20 分钟内完成了我想要的代码隐藏,我想尝试 MVVM 模式,我需要几个小时来解决简单的问题。

我正在使用 EventAggregator 寻找一些解决方案,但这需要使用像 Prism、Caliburn.Micro 这样的框架。所以我得到了虚拟机和 View 之间的某种通信。

最佳答案

您可以将包含所需方法的接口(interface)传递给 MainViewModel

interface IMainView
{
    void Init(PleaseWaitViewModel viewModel);
    void ShowDialog();
    void Close();
}

public class MainViewModel
{
     private IMainView _view;
     public MainViewModel(IMainView view)
     {
         _view = view;


        backgroundWorker = new BackgroundWorker() { WorkerSupportsCancellation = true };
        backgroundWorker.DoWork += BackgroundWorker_DoWork;
        backgroundWorker.RunWorkerCompleted += 
        BackgroundWorker_RunWorkerCompleted;

        var pleaseWaitViewModel = new PleaseWaitViewModel(backgroundWorker);
        _view.Init(pleaseWaitViewModel);
     }

    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _view.Close();
}

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // Some work
    Thread.Sleep(5000);
}

private void DoSomethingImpl(object parameter)
{
    _view.ShowDialog();
}
}

关于c# - 带有所有者的 MVVM showDialog 并在后台工作人员完成时关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49599756/

相关文章:

wpf - 在同一应用程序中使用 Prism 和 GalaSoft MVVM 工具包是否多余?

.net-3.5 - 使用MEF + MVVM照明工具包时组成零件的理想场所?

c# - 在任务中报告/记录

c# 服务器无法识别android

c# - C# 3.0 中 var 关键字的优势

c# - 按钮的 Xamarin 自定义渲染器 (iOS)

c# - 如何使用 Handle 中的协程 - Caliburn Micro 中 IResult 的实现

.net - Blend 打开时没有语言和版本

c# - 从 WPF 中的不同位置访问表单

c# - 可以显示来自资源 URI 属性的 .png 和基于矢量的图像的 MenuItem