Mvvm UWP ContentDialog调用

Mvvm UWP ContentDialog调用,mvvm,modal-dialog,winrt-xaml,uwp,template10,Mvvm,Modal Dialog,Winrt Xaml,Uwp,Template10,我正在使用UWP和模板10按照MVVM模式构建GUI应用程序。作为应用程序的一部分,我需要通过按下主页上的按钮来调用一个内容对话框。为此,在独立的.xaml文件中创建了单独的ContentDialog: <ContentDialog x:Class="UWP1.Views.Speech" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.

我正在使用UWP和模板10按照MVVM模式构建GUI应用程序。作为应用程序的一部分,我需要通过按下主页上的按钮来调用一个内容对话框。为此,在独立的.xaml文件中创建了单独的ContentDialog:

<ContentDialog
    x:Class="UWP1.Views.Speech"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWP1.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="Dictate"
    PrimaryButtonText="Accept"
    SecondaryButtonText="Cancel"
    PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
    SecondaryButtonClick="ContentDialog_SecondaryButtonClick"
    >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>
            <Button Margin="15" Content="Dictate" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch"/>
        <Button  Margin="15" Content="Clear Text" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch"/>
        <TextBlock Grid.Row="1" Grid.ColumnSpan="2" Text="Tap 'Dictate', and speak" FontSize="12" />
            <TextBlock Margin="0 10 0 0" Grid.Row="2" Grid.ColumnSpan="2" Text="Message Dication" HorizontalAlignment="Center" FontSize="24"  />
        <ScrollViewer Grid.Row="3" Grid.ColumnSpan="2" Height="300">
            <TextBox Margin="5 5 5 10"  AcceptsReturn="True"  />
        </ScrollViewer>
    </Grid>
</ContentDialog>

按下按钮(因为我需要保持视图和视图模型的逻辑分离),在主页中打开/调用它的正确方式是什么

我现在怎么做:

在主页面中,我调用命令,该命令依次创建ContentDialog实例并显示:

 <AppBarButton Grid.Column="1" Icon="Microphone" IsCompact="True" HorizontalAlignment="Right" Command="{Binding DictateCommand}"/>

        public ICommand DictateCommand { get; set; }

        public async void Dictate(object obj)
        {
            var contentDialog = new Speech();
            await contentDialog.ShowAsync();
        }

公共ICommand命令{get;set;}
公共异步无效指令(对象obj)
{
var contentDialog=新语音();
等待contentDialog.ShowAsync();
}
对我来说,这看起来像是MVVM模式的突破。你能帮我用正确的方法做这件事吗

编辑:

我已经实现了dialog服务,并将其注入到主视图模型中。
然而,我遇到了另一个障碍。对于这个对话框,我创建了单独的视图模型和属性,它们封装了对话框文本框的值。当我按下对话框上的“接受”按钮时,我需要这个值反映在我的主视图上。所以我需要将对话框的文本框值从对话框的视图模型传递到主视图模型。我应该执行另一个依赖项注入来处理它吗?

MVVM中建议的解决方案是不要直接在ViewModel中创建
语音对话框的实例,创建
语音对话框服务

public interface ISpeechDialogService
{
    Task ShowAsync();
}

public class SpeechDialogService : ISpeechDialogService
{
    public async Task ShowAsync()
    {
        var contentDialog = new Speech();
        await contentDialog.ShowAsync();

    }
}
并将此服务注入您的
ViewModel
构造函数中

public class AbcViewModel
{
    readonly ISpeechDialogService _dialog;

    public AbcViewModel(ISpeechDialogService dialog)
    {
        _dialog = dialog;
    }

    public async void Dictate(object obj)
    {
        await _dialog.ShowAsync();
    }
}
你有四个选择

第一个是服务,就像@Ask too much解释一样。事实上,如果你喜欢,这是一个很好的解决方案

第一个解决方案的好处是它是可重用的。如果您不重用此UI,老实说,一个专用的服务可能会有点过头

TWO第二个是视图模型事件。也就是说,您的页面可以订阅视图模型的事件(我们称之为ShowContentDialog),当视图模型引发该事件时,您的页面将处理其显示

这种方法的好处是,与第一种方法一样,您可以将工作转移到另一个类。在本例中,您创建的可能是一次性解决方案,而不需要服务、服务接口或以某种方式注入该服务。如果你不是在等待活动的结果,那么我认为这是一个解决99%像你这样问题的想法

THREE第三种方法是使用可以绑定到属性的不同控件。例如,由于您已经在使用模板10,因此可以使用具有IsModal属性的ModalDialog控件。视图模型中的属性(我们称之为IsModalVisible)可用于控制对话框,而无需与对话框耦合

这其中的好处在于,您可以从视图模型的逻辑调用对话框,就像前两种方法一样。但与第一个不同,您不需要服务。与第二个不同,您不需要处理程序。这是最“数据绑定”的方式,很可能也是我要做的

FOUR第四种方法是使用消息传递。消息传递是一个视图模型用于与另一个视图模型通信的机制。在这种情况下,您可以使用来自视图模型的消息(以及我们可能称之为ShowDialog的消息),该消息不是在另一个视图模型中,而是在您的页面中被监听。这也行

缺点是您需要一个消息传递解决方案,但您可能已经有了。好的一面是,处理可视信息的逻辑可以在任何时候重新定位,因为消息可以多播给任何收听的人

如果我是你,也许我会先考虑数字3。如果不进一步了解你的应用程序场景,我不能确定。不过,您是一名开发人员。这四个选项都很好。请确保不要试图将UIElement传递到视图模型中。这是不必要的肮脏:)


祝你好运

使用选项3,模态对话框的创建方式是否与模板10的搜索示例项目相同?我需要一个对话框,用户可以按“是”或“否”,我需要知道在调用对话框的ViewModel中,他们选择了哪个选项……但我不确定如何做到这一点。