Wpf MVVM多对话框

Wpf MVVM多对话框,wpf,mvvm,caliburn.micro,Wpf,Mvvm,Caliburn.micro,我用的是caliburn micro。我的问题是如何管理对话框。 最大的问题是,当不使用窗口时,您的代码不会停止并等待 所以我做了类似的事情 public void ShowDialog(IScreen dialogModel, Action<object> callback = null) { ActivateItem(dialogModel); if (callback != null) dialogModel.Deactivated += de

我用的是caliburn micro。我的问题是如何管理对话框。 最大的问题是,当不使用窗口时,您的代码不会停止并等待

所以我做了类似的事情

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

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

}

还因为我想一次显示一个对话框,所以扩展了Collection.OneActive。但这也有问题。在停用事件回调中,如果我想关闭,我无法关闭所有!因为它会在内存中保留触发停用后的下一个引用,即使清除它,它也会再次出现。

在对话框之间移动时,使用类跟踪状态信息,而不是像原始示例中所示嵌套闭包,怎么样

我认为你在正确的轨道上,但你似乎有两个问题:

  • 您所做的嵌套量对代码的清晰度没有好处
  • 您需要一种更好的方法来捕获对话框之间的局部变量和状态信息
  • 要解决第一个问题,我建议将逻辑分解为不同的方法。每次停用对话框时,您都可以有一个方法来处理应该在之后执行的逻辑

    要解决第二个问题,您可以尝试创建一个类,该类负责存储要在对话框之间传递的信息。这个类的一个实例可以作为一个参数传入每个方法,该方法将在对话框停用时执行

    以下是您可以实现此目标的方法:

    导线等级

    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.
        }
    }
    
    公共类对话框testsviewmodel:Conductor.Collection.OneActive
    {
    /// 
    ///显示对话框并在必要时执行其回调。
    /// 
    ///要显示的对话框视图模型。
    ///对话框关闭时要执行的回调。
    public void ShowDialog(IScreen dialogModel,Action callback=null)
    {
    //显示对话框。
    ActivateItem(dialogModel);
    //如果有回调,请在对话框关闭/停用时调用它。
    if(callback==null)返回;
    dialogModel.Deactivated+=(发送方,参数)=>callback();
    }
    /// 
    ///此方法启动对话框链。
    /// 
    public void ShowFirstDialog()
    {
    //创建新上下文。这将保存状态信息
    //当它在对话框之间传递时。
    var context=newtestdialogcontext();
    //创建第一个对话框的视图模型。
    var viewModel=new FirstDialogViewModel();
    //显示第一个对话框。
    ShowDialog(viewModel,()=>OnFirstDialogDeactivated(viewModel,context));
    }
    /// 
    ///第一个对话框关闭时要执行的逻辑。
    /// 
    ///第一个对话框的视图模型。
    ///国家信息。
    私有void OnFirstDialogDeactivated(FirstDialogViewModel viewModel、TestDialogContext上下文)
    {
    //检查此处的视图模型,并将状态信息存储在上下文中。
    如果(viewModel.SomethingIsChecked)
    {
    context.ShouldShowSecondDialog=true;
    }
    //使用视图模型或上下文中的信息来决定是否显示下一个对话框。
    //您还可以决定接下来在此处显示哪个对话框。
    if(context.ShouldShowSecondDialog)
    {
    var secondDialog=new SecondDialogViewModel();
    ShowDialog(secondDialog,()=>OnSecondDialogDeactivated(上下文));
    }
    }
    /// 
    ///第二个对话框关闭时要执行的逻辑。
    /// 
    ///国家信息。
    私有void OnSecondDialogDeactivated(TestDialogContext上下文)
    {
    //多做事。
    }
    }
    
    对话框上下文类

    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.
        }
    }
    
    在这里,您可以存储需要在对话框之间传递的状态信息。我只是举了一个例子,但是你可以在这里放很多信息

    /// <summary>
    /// State information to be passed between dialogs.
    /// </summary>
    public class TestDialogContext
    {
        public bool ShouldShowSecondDialog { get; set; }
    }
    
    //
    ///对话框之间要传递的状态信息。
    /// 
    公共类TestDialogContext
    {
    公共布尔值应显示第二个对话框{get;set;}
    }
    
    谢谢您的建议!我会尝试用你的建议写下我所有的案例,并给出答案。但有一个小问题,也许我需要一个黑客。假设我显示了一个付款对话框,然后我决定需要第二个对话框。到目前为止还不错。但如果我显示第二个密码对话框,那么我究竟如何才能停用所有屏幕?在这里,我在执行此操作时遇到问题,因为在停用CM后,它会保留对下一个viewModel的引用,即使您清除并关闭所有视图模型,它也会再次添加它。唯一有效的解决方法是不使用TryClose,而是(this.Parent作为DialogConductorViewModel)。停用Item(this,false);