简体   繁体   English

MVVM多对话框令人头疼

[英]MVVM multiple Dialogs headache

I am using caliburn micro. 我正在使用caliburn micro。 My problem is how to manage dialogs. 我的问题是如何管理对话框。 The biggest problem is that because when not using window your code doesnt stop and wait. 最大的问题是,因为当不使用窗口时,您的代码不会停止并等待。

So i did something like this. 所以我做了这样的事情。

public void ShowDialog(IScreen dialogModel, Action<object> callback = null)
{
    ActivateItem(dialogModel);

    if (callback != null)
        dialogModel.Deactivated += delegate { callback(dialogModel); };

}

This has lots of problem.For example in case i want to show dialog A and then at callback i want to show dialog B under certain cases there comes a problem.I have to write an extra function for DoSomething in order not to duplicate.And i loose all the other local variables..The problem is bigger when more levels are required.. 这有很多问题。例如,在某些情况下,我想显示对话框A,然后在回调中想显示对话框B,这是有问题的。为了避免重复,我必须为DoSomething编写一个额外的函数。我松开所有其他局部变量。.当需要更多级别时,问题更大。

    showDialog(A, (cb)=>{

    if(...) {

    showDialog(B,(cb2)=>{
       DoSomething();

    });

    }
    else{
    DoSomething();
    }
});

Also because i wanted to show one dialog at a time i extended Collection.OneActive . 也因为我想一次显示一个对话框,所以我扩展了Collection.OneActive。 But this had problem too. 但这也有问题。 In deactivate event callback i couldnt close all if i wanted to! 在停用事件回调中,如果我愿意,我无法关闭所有功能! Because it keeps in memory the next reference after Deactivated is triggered and even if you clear it it comes again.. 因为它保留在内存中,所以触发了“停用”后的下一个引用,即使您清除它,它也会再次出现。

How about using a class to track state information as you move between dialogs, rather than nesting closures as shown in your original example? 如何在对话框之间移动时使用类来跟踪状态信息,而不是像原始示例中那样嵌套闭包?

I think you're on the right track, but it seems like you have two problems: 我认为您走在正确的道路上,但是似乎您有两个问题:

  1. The amount of nesting that you're doing is not good for code clarity. 您正在进行的嵌套数量不足以使代码清晰。
  2. You need a better way to capture local variables and state information between dialogs. 您需要一种更好的方法来捕获对话框之间的局部变量和状态信息。

To solve the first problem, I'd recommend breaking apart your logic into different methods. 为了解决第一个问题,我建议将您的逻辑分解为不同的方法。 Every time a dialog is deactivated, you could have a method to handle the logic that should be executed afterward. 每次停用对话框时,您都可以使用一种方法来处理随后应执行的逻辑。

To solve the second problem, you might try creating a class that is responsible for storing the information that you want to pass between dialogs. 要解决第二个问题,您可以尝试创建一个类,该类负责存储要在对话框之间传递的信息。 An instance of this class could be passed in as an argument into each method that is to be executed upon dialog deactivation. 此类的实例可以作为参数传递给将在停用对话框后执行的每个方法。

Here's how you could accomplish this: 这是完成此操作的方法:

Conductor Class 导体类

public class DialogTestsViewModel : Conductor<object>.Collection.OneActive
{
    /// <summary>
    /// Shows a dialog and executes its callback if necessary.
    /// </summary>
    /// <param name="dialogModel">The dialog view model to be shown.</param>
    /// <param name="callback">The callback to be executed when dialog is closed.</param>
    public void ShowDialog(IScreen dialogModel, Action callback = null)
    {
        // Show the dialog.
        ActivateItem(dialogModel);

        // If there is a callback, call it when dialog is closed / deactivated.
        if (callback == null) return;
        dialogModel.Deactivated += (sender, args) => callback();
    }

    /// <summary>
    /// This method kicks off the dialog chain.
    /// </summary>
    public void ShowFirstDialog()
    {
        // Create a new context. This will hold state information
        // as it is passed between dialogs.
        var context = new TestDialogContext();

        // Create the first dialog's view model.
        var viewModel = new FirstDialogViewModel();

        // Show the first dialog.
        ShowDialog(viewModel, () => OnFirstDialogDeactivated(viewModel, context));
    }

    /// <summary>
    /// Logic to be executed when the first dialog is closed.
    /// </summary>
    /// <param name="viewModel">The first dialog's view model.</param>
    /// <param name="context">The state information.</param>
    private void OnFirstDialogDeactivated(FirstDialogViewModel viewModel, TestDialogContext context)
    {
        // Check the view model here and store state information inside the context.
        if (viewModel.SomethingIsChecked)
        {
            context.ShouldShowSecondDialog = true;
        }

        // Use information in the view model or the context to decide if we should show the next dialog.
        // You could also make a decision about which dialog to show next here.
        if (context.ShouldShowSecondDialog)
        {
            var secondDialog = new SecondDialogViewModel();
            ShowDialog(secondDialog, () => OnSecondDialogDeactivated(context));
        }
    }

    /// <summary>
    /// Logic to be executed when the second dialog is closed.
    /// </summary>
    /// <param name="context">The state information.</param>
    private void OnSecondDialogDeactivated(TestDialogContext context)
    {
        // Do more stuff.
    }
}

Dialog Context Class 对话框上下文类

Here is where you would store the state information that needed to be passed between dialogs. 在这里您将存储需要在对话框之间传递的状态信息。 I've only included one property here as an example, but you could put a lot of info here. 我仅在此处包括一个属性作为示例,但是您可以在此处添加很多信息。

/// <summary>
/// State information to be passed between dialogs.
/// </summary>
public class TestDialogContext
{
    public bool ShouldShowSecondDialog { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM