wpf Caliburn ShowDialog 和 MessageBox

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17510704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:10:26  来源:igfitidea点击:

Caliburn ShowDialog and MessageBox

c#wpfmvvmmessageboxcaliburn.micro

提问by Mare Infinitus

I'm making a small demo application for MVVM with caliburn.

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

Now I want to show a MessageBox, but the MVVM way.

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

For dialogs I created an event, that is handled in the ShellView(the root view) and just calls WindowManager.ShowDialogwith a Dialogs ViewModeltype. Seems to stick to MVVM for me.

对于对话框,我创建了一个事件,该事件在ShellView(根视图)中处理并且仅WindowManager.ShowDialog使用 DialogsViewModel类型进行调用。对我来说似乎坚持使用 MVVM。

But what is the way to show a messagebox and get its result (Okay or cancel)?

但是显示消息框并获得其结果的方法是什么(好的或取消)?

I already saw this question, but it contains no answer either.

我已经看到了这个问题,但它也没有答案。

Mr Eisenberg hisself answers with

艾森伯格先生亲自回答

"Caliburn has services built-in for calling custom message boxes."

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

Can anyone tell what he means with that? I don't see it in the samples.

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

采纳答案by Ibrahim Najjar

In the article A Billy Hollis Hybrid Shell(written by the framework coordinator)the author showed a nice way to handle both dialog and message boxes, but he used dependency injection (you can go without DI of course but it makes things simpler). The main idea is that you can let your main window, the one used as the application shell implement an interface that looks something like this:

在文章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);

    }

and then he registers this interface with the IoC container, I guess you can use your imagination from there on and if you don't have time then you can look at the source codethat accompanies the article.

然后他将这个接口注册到 IoC 容器中,我想你可以从那里开始发挥你的想象力,如果你没有时间那么你可以查看文章随附的源代码

回答by Patryk ?wiek

As you mentioned, you just prepare the view model (e.g. ConfirmationBoxViewModel) and an appropriate view. You'll have to create two actions (after inheriting the view model from Screen, which is necessary to use TryClose. You can always implement IScreeninstead, but that would be more work):

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

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

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

and then in your other view model:

然后在你的另一个视图模型中:

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

Notice that after the dialog closes, you can access the view model properties if you need to pull additional data from the dialog (e.g. Selected item, display name etc).

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

回答by superjos

When the root/main/shell view-model implements a kind of DialogServiceinterface, every other view-model needing to show dialogs will end up with a dependency on the root view-model. Sometimes this might not be desiderable, e.g. if it could cause a dependency loop:
DialogService(aka RootViewModel) -> SomeViewModel-> RootViewModel.

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

A more involvedapproach to break this dependency chain (and actually invert it) is the following:

打破这种依赖链(并实际上反转它)的更复杂的方法如下:

  • Implement a behavior that detects Window.OnSourceInitializedevent and attach it to main view Windowcomponent. That is the event fired when the window handle is available. Upon event, behavior will notify some handler passed in via attached property:
  • 实现检测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);
  }
}
  • DialogServiceexposes a handler - or interface - as requested by behavior:
  • DialogService根据行为的要求公开处理程序或接口:
public class DialogService : IWindowListener
{
  // ...
  public void SourceInitialized(Window rootWindow) { /* ... */ }
}
  • In root view-model, (indirectly) get the DialogServiceinjected as a dependency. During construction, sets view-model bound property, WindowListener, to the DialogServicehandler/interface:
  • 在根视图模型中,(间接)将DialogService作为依赖注入。在构建期间,将视图模型绑定属性WindowListener, 设置为DialogService处理程序/接口:
public MainViewModel(IWindowListener dialogServiceInDisguise)
{
  WindowListener = dialogServiceInDisguise;
}

public IWindowListener WindowListener { get; private set; }

Doing so, the DialogService is able to get a hold of root Window, and whichever view-model needs to show a dialog does not create a(n indirect) dependency on main view-model.

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