【问题标题】:Caliburn ShowDialog and MessageBoxCaliburn ShowDialog 和 MessageBox
【发布时间】:2013-07-07 09:09:25
【问题描述】:

我正在使用 caliburn 为 MVVM 制作一个小型演示应用程序。

现在我想显示一个MessageBox,但是是 MVVM 方式。

对于对话框,我创建了一个事件,在 ShellView(根视图)中处理 只需使用 Dialogs ViewModel 类型调用 WindowManager.ShowDialog。 对我来说似乎坚持使用 MVVM。

但是显示消息框并获得其结果的方式是什么(Okay 或 cancel)?

我已经看到this question,但它也没有答案。

艾森伯格先生自己回答

“Caliburn 具有用于调用自定义消息框的内置服务。”

谁能说出他的意思?我在示例中没有看到它。

【问题讨论】:

    标签: c# wpf mvvm messagebox caliburn.micro


    【解决方案1】:

    正如您所提到的,您只需准备视图模型(例如ConfirmationBoxViewModel)和适当的视图。您必须创建两个操作(在从Screen 继承视图模型之后,这是使用TryClose 所必需的。您始终可以实现IScreen,但这会更有效):

    public void OK()
    {
        TryClose(true);
    }
    
    public void Cancel()
    {
        TryClose(false);
    } 
    

    然后在您的其他视图模型中:

    var box = new ConfirmationBoxViewModel()
    var result = WindowManager.ShowDialog(box);
    if(result == true)
    {
    // OK was clicked
    }
    

    请注意,对话框关闭后,如果您需要从对话框中提取其他数据(例如,所选项目、显示名称等),您可以访问视图模型属性。

    【讨论】:

    • 非常感谢!好的,这正在制作一个看起来像消息框的对话框。但是有没有一种简单的方法来封装一个 Messagebox?有没有一种解耦的方式来通过事件实现这一目标? MessageBox 用途广泛,我很想以某种方式使用它。
    • 我真的不这么认为,至少我知道没有真正简单的方法。考虑到您可以创建一个易于定制且易于使用的类似于对话框的视图模型和视图,我认为没有任何理由包装默认的 MessageBox...
    【解决方案2】:

    A Billy Hollis Hybrid Shell 文章中(由框架协调员编写)作者展示了一种处理对话框和消息框的好方法,但他使用了依赖注入(你可以不用当然是 DI,但它让事情变得更简单)。主要思想是,您可以让用作应用程序外壳的主窗口实现如下所示的界面:

    public interface IDialogManager
        {
    
            void ShowDialog(IScreen dialogModel);
            void ShowMessageBox(string message, string title = null, MessageBoxOptions options = MessageBoxOptions.Ok, Action<IMessageBox> callback = null);
    
        }
    

    然后他将这个接口注册到IoC容器中,我想你可以从那里发挥你的想象力,如果你没有时间可以看一下文章随附的source code

    【讨论】:

    • 非常感谢!我唯一的问题是返回用户在消息框(或对话框)中选择的内容。必须仔细看看。
    • 好吧,它是 Silverlight 和 MEF,所以对我来说不是很清楚。
    • @MareInfinitus 您可以通过Action&lt;IMessageBox&gt; 回调确定用户在ShowMessageBox 方法中选择了什么。另一方面,如果您不了解 silverlight 和 MEF,我已经下载了示例并使用 Ninject 将其转换为 WPF。如果你愿意,我可以把它上传给你。
    • @MareInfinitus 你可以下载它HelloScreensWPF
    • @IbrahimNajjar 答案中提到的所有链接都已过期。你有更新的链接吗?
    【解决方案3】:

    当 root/main/shell 视图模型实现一种 DialogService 接口时,所有其他需要显示对话框的视图模型最终都会依赖于根视图模型。有时这可能是不可取的,例如如果它可能导致依赖循环:
    DialogService(又名 RootViewModel)-> SomeViewModel -> RootViewModel .

    一种更多参与的方法来打破这个依赖链(实际上是反转它)如下:

    • 实现检测Window.OnSourceInitialized 事件的行为并将其附加到主视图Window 组件。这是当窗口句柄可用时触发的事件。发生事件时,行为将通知通过附加属性传入的一些处理程序:
    <my:WindowSourceBehavior InitListener="{Binding WindowListener}" />
    
    public class WindowSourceBehavior : Behavior<Window>
    {
      // ...
      // boilerplate code for IWindowListener InitListener dependency property
      // ...
    
      attachedWindow.SourceInitialized += (sender, evt) =>
      {
         // ...
         InitListener.SourceInitialized(sender as Window);
      }
    }
    
    • DialogService 根据行为请求公开处理程序或接口:
    public class DialogService : IWindowListener
    {
      // ...
      public void SourceInitialized(Window rootWindow) { /* ... */ }
    }
    
    • 在根视图模型中,(间接地)将 DialogService 作为依赖项注入。在构造过程中,将视图模型绑定属性 WindowListener 设置为 DialogService 处理程序/接口:
    public MainViewModel(IWindowListener dialogServiceInDisguise)
    {
      WindowListener = dialogServiceInDisguise;
    }
    
    public IWindowListener WindowListener { get; private set; }
    

    这样做,DialogService 能够获得根窗口,并且任何需要显示对话框的视图模型都不会创建(n 间接)对主视图模型的依赖。

    【讨论】:

    • 我看不到接受的答案在哪里与主/外壳视图模型有(间接)依赖关系。伪装很多东西也不是最好的主意,我喜欢明确说明依赖关系和所做的事情。
    • 如果我做对了,在这种情况下,您的主视图模型实现了IDialogManager 接口,我猜该接口将被注入到需要显示对话框的其他视图模型中。因此,许多视图模型最终将取决于根视图模型。顺便说一句,在这种情况下,它不会是对根视图模型的显式依赖,因为他们不需要。同样,这将是对 IDialogManager 接口伪装的依赖,而不知道它实际上是根视图模型。顺便说一句,我认为这是正确的。你怎么看?
    • 不,DialogManager 只是注入的,因此对 rootviewmodel 没有(直接或间接)依赖。只有对话框管理器,它采用 ViewModel 并将它们与视图组合,就像 caliburn 那样。 DialogManager 本身不是 rootviewmodel,而是另一个类,它只做对话管理。所以在我看来,这是一种非常清晰的以 MVVM 方式进行对话的方式(因为 ViewModel 只能看到其他 ViewModel,不依赖于视图)。尽管 DialogManager 不是 rootviewmodel,如前所述。但是您的解决方案肯定会很有用。
    • 这是让我得出结论的部分:你可以让你的主窗口[...]实现一个接口公共接口IDialogManager。这不是说根视图模型实现了 DialogManager 接口吗?
    • 如果你实现了接口,那么它就实现了。但是在接受答案的代码中,它被注入了,即它使用一些对话框管理器,而不是一个对话框管理器。
    猜你喜欢
    • 2023-03-28
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 2012-01-29
    • 2012-10-24
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    相关资源
    最近更新 更多