【问题标题】:How to Handle MessageBox Dialogs When Using the MVVM Pattern(MVVM Light ToolKit)使用 MVVM 模式时如何处理 MessageBox 对话框(MVVM Light ToolKit)
【发布时间】:2013-03-03 11:34:12
【问题描述】:

我正在制作一个 windows phone 7 并尝试使用 MVVM 来完成它。我想保持我的视图模型尽可能干净,但我不确定如何制作一个对话框。我正在使用 MVVM light,我知道他们有消息系统或其他东西,但不确定如何使用它。

我想使用Guide.BeginShowMessageBox,因为这似乎提供了比标准对话框更多的功能。

如何在不破坏 MVVM 模式的情况下做到这一点。当我加载视图时,我希望触发加载的触发器,然后检查一些条件。如果满足条件,则显示对话框。

//Vm

public RelayCommand MainPageLoaded
    {
        get
        {
            if (!NetworkInterface.GetIsNetworkAvailable())
            {
                // breaks MVVM now as have view code in viewmodel. Need to take out somehow
                Guide.BeginShowMessageBox("Test", "Test network", new List<string>() { "Yes", "No" }, 0, MessageBoxIcon.Warning, asyncResult =>
                    {
                        int? returned = Guide.EndShowMessageBox(asyncResult);
                        // if yes then work offline mode? Maybe another property in ViewModel will get set to say offline mode?
                    }, null);
            }
            return null;
        }
        set
        {
            // Not sure what to put here.
        }
    }

// 查看

<i:Interaction.Triggers>
    <i:EventTrigger>
        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding MainPageLoaded}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

编辑 我遇到的另一个问题是。我有一个绑定到存储在此属性中的一些数据的列表

   public ObservableCollection<ContactGroup> ContactGroups { get; set; }

然后点击我有一个应该触发的中继命令

 public ICommand GroupContactTapped
        {
            get
            {
                return new RelayCommand<GestureEventArgs>(e =>
                {
                    var selectedTextBlock = e.OriginalSource as TextBlock;

                    MessageBox.Show(selectedTextBlock.Tag.ToString());
                });
            }
        }

但我不知道如何在不将源转换为文本块的情况下找到“点击”的对象。

【问题讨论】:

  • 您的实际问题是什么?
  • 更新了我的问题以使其清楚。还添加了一些我一直在尝试的代码。

标签: c# windows-phone-7 mvvm mvvm-light


【解决方案1】:

遵循“MVVM 模式”的真正含义是非常主观的事情。
例如,有些人会说您不应该从 VM 显示/启动消息框(任何类型),而其他人会说这很好。

与任何歧义一样,您需要平衡对模式的遵守、最适合特定项目的模式以及适合开发和维护代码库的人员的模式。

就 MvvmLight 而言,它使用的消息传递系统用于从视图模型到另一个视图模型或视图进行通信,而不是用于向用户显示消息。

如果您打算使用Guide.BeginShowMessageBox,尤其是从视图模型中,请注意它是非阻塞的。如果您希望它的行为类似于“常规”MessageBox,则需要将其与 ManualResetEvent 一起使用,这样在显示消息框时就无法继续与应用交互。

【讨论】:

  • 是的,这就是我想用 MVVM 模式来奖励什么努力。我的意思是有时用一种方法来做这件事会更容易、更干净,而且可能不是 100% 正确,然后编写大量代码并使其更难阅读。如果我在哪里做 MVVM 方式,那你怎么做呢?
  • @chobo2 没有“一种 MVVM 方式”来显示消息框。如果您想尽可能“纯粹”:将服务注入可以显示消息框的视图模型,然后在需要时调用该服务以显示消息框。
  • 嗯,对我来说有点奇怪,因为当我想到服务时,我会想到服务层应该尽可能干净,并且其中也没有那种代码,但那是针对 Web 应用程序的。所以每次我需要在虚拟机中做类似的事情时,我都需要使用服务?这种情况下怎么办?我有一个手势(RelayCommand),我想找到它的源 var selectedTextBlock = e.OriginalSource as TextBlock;我是否必须将该行移至服务并传入 e?
  • @chobo2 在那种情况下,您可能不需要服务,并且您不应该引用 TextBlock。服务通常用于与 ViewModel 之外的项目进行交互,例如文件系统或 UI(例如,显示消息框)。不要直接引用 TextBlock,添加一个命令参数,即您真正感兴趣的 [sub]viewModel 或 viewmodel 属性。
  • 我不明白我已经有一个 RelayCommand 设置,其中包含我想要捕获的事件,但我不明白 [sub]viewModel 的意思。你说我需要将 Source 传递给另一个 Vm?
【解决方案2】:

Cimbalino Phone Windows Toolkit 中有一个MessageBoxService! 您可以在 MVVM 架构中使用它。

【讨论】:

    【解决方案3】:

    假设您有一个托管所有其他视图的主页/视图,例如主窗口: 我从视图模型发送一个消息事件,对话框在主窗口后面的代码中处理。这是我的项目中唯一的代码隐藏,所以我发现项目的其余部分可以严格地是 MVVM 是可以接受的,除了这个例外。

    我发送带有以下内容的消息(从 VB 转换,因此可能需要工作):

    object message = new DialogMessage("YourMessage", YourFunctionThatHandlesCallback) {
        Button = MessageBoxButton.YesNo,
        Caption = "Caption Goes Here"
    };
    Messenger.Default.Send(message);
    

    我在后面的主页代码中注册了如下对话框:

    Partial Public Class MainWindow
      Inherits Window
    
      Public Sub New()
        InitializeComponent()
    
        ''single initialization of messanger for catching message box
        Messenger.[Default].Register(Of DialogMessage)(Me, Sub(msg)
                                                               Dim result = MessageBox.Show(msg.Content, msg.Caption, msg.Button, MessageBoxImage.Warning)
                                                               ''Send callback
                                                               msg.ProcessCallback(result)
                                                           End Sub)
      End Sub
    End Class
    

    我无法成功转换 C# lambda,所以我不得不将它留在 VB 中。希望这会有所帮助

    【讨论】:

      猜你喜欢
      • 2012-01-26
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      相关资源
      最近更新 更多