5

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

现在我想展示一个MessageBoxMVVM 方式。

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

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

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

艾森伯格先生自己回答

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

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

4

3 回答 3

7

正如您所提到的,您只需准备视图模型(例如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
}

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

于 2013-07-07T09:40:14.290 回答
5

在文章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 容器中,我想你可以从那里发挥你的想象力,如果你没有时间,你可以看看文章随附的源代码。

于 2013-07-07T12:35:49.477 回答
0

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

于 2015-03-30T19:30:54.777 回答