UWP ContentDialog 调用
UWP ContentDialog Invocation
我正在使用 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>
在我的主页中按下按钮 open/invoke 它的正确方法是什么(因为我需要将视图和视图模型的逻辑分开)?
我现在是怎么做的:
我从主页面调用 DictateCommand,后者又创建了一个 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();
}
对我来说,这看起来像是违反了 MVVM 模式。你能帮我以正确的方式做到这一点吗?
编辑:
我已经实现了对话框服务并将其注入到主视图模型中。
但是,我遇到了另一个障碍。对于这个对话框,我创建了单独的视图模型和封装对话框文本框值的 属性。当我按下对话框上的 'accept' 按钮时 - 我需要将此值反映在我的主视图上。所以我需要将对话框的文本框值从对话框的视图模型传递到主视图模型。我是否应该执行另一个依赖注入来处理它?
建议的 MVVM 解决方案是不要直接在 ViewModel 中创建 Speech Dialog
的实例,而是创建 SpeechDialogService
.
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();
}
}
你有四个选择。
ONE 第一个是服务,就像@Ask-too-much 解释的那样。事实上,如果您喜欢,这是一个漂亮的解决方案。
The benefits of the first solution are that it is reusable. If you are not reusing this UI, a dedicated service might be overkill, to be honest.
两个 第二个是视图模型事件。也就是说,您的页面可以订阅您的视图模型的事件(我们称之为 ShowContentDialog),当它由视图模型引发时,您的页面会处理它的呈现。
The benefits this approach is that, just like the first approach, you are offloading the effort to another class. In this case, you are creating what is likely a one-off solution without needing a service, a service interface, or injection of that service somehow. If you are not waiting for the result of the event, then I think this is idea for 99% of issues like yours.
THREE 第三种方法是使用可以绑定到 属性 的不同控件。例如,由于您已经在使用模板 10,您可以使用具有 IsModal 属性 的 ModalDialog 控件。视图模型中的 属性(我们称它为 IsModalVisible)可用于控制对话框而无需耦合它。
The good part of this is that you get to invoke the dialog from the logic of your view-model, just like the first two approaches. But unlike the first, you do not need a service. Unlike the second, you do not need a handler. It's the most "data binding" way to do it, and likely what I would do.
FOUR 第四种方法是使用消息传递。消息传递是一个视图模型用来与另一个视图模型通信的机制。在这种情况下,您可以使用来自您的视图模型的消息传递(带有我们可能称为 ShowDialog 的消息),它被监听,而不是在另一个视图模型中,而是在您的页面中。这也可以正常工作。
The down side to this is that you need a messaging solution, but you might already have that. The up-side is that the logic for handling the visual could be relocated at any time as Messaging is multicasted to anyone listening.
如果我是你,我可能会首先考虑第 3 个。如果对您的应用场景没有更多的了解,我无法确定。不过,您是开发人员。所有这四个选项都很好。请确保不要被诱惑将 UIElement 传递到您的视图模型中。那是不必要的肮脏:)
祝你好运!
我正在使用 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>
在我的主页中按下按钮 open/invoke 它的正确方法是什么(因为我需要将视图和视图模型的逻辑分开)?
我现在是怎么做的:
我从主页面调用 DictateCommand,后者又创建了一个 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();
}
对我来说,这看起来像是违反了 MVVM 模式。你能帮我以正确的方式做到这一点吗?
编辑:
我已经实现了对话框服务并将其注入到主视图模型中。 但是,我遇到了另一个障碍。对于这个对话框,我创建了单独的视图模型和封装对话框文本框值的 属性。当我按下对话框上的 'accept' 按钮时 - 我需要将此值反映在我的主视图上。所以我需要将对话框的文本框值从对话框的视图模型传递到主视图模型。我是否应该执行另一个依赖注入来处理它?
建议的 MVVM 解决方案是不要直接在 ViewModel 中创建 Speech Dialog
的实例,而是创建 SpeechDialogService
.
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();
}
}
你有四个选择。
ONE 第一个是服务,就像@Ask-too-much 解释的那样。事实上,如果您喜欢,这是一个漂亮的解决方案。
The benefits of the first solution are that it is reusable. If you are not reusing this UI, a dedicated service might be overkill, to be honest.
两个 第二个是视图模型事件。也就是说,您的页面可以订阅您的视图模型的事件(我们称之为 ShowContentDialog),当它由视图模型引发时,您的页面会处理它的呈现。
The benefits this approach is that, just like the first approach, you are offloading the effort to another class. In this case, you are creating what is likely a one-off solution without needing a service, a service interface, or injection of that service somehow. If you are not waiting for the result of the event, then I think this is idea for 99% of issues like yours.
THREE 第三种方法是使用可以绑定到 属性 的不同控件。例如,由于您已经在使用模板 10,您可以使用具有 IsModal 属性 的 ModalDialog 控件。视图模型中的 属性(我们称它为 IsModalVisible)可用于控制对话框而无需耦合它。
The good part of this is that you get to invoke the dialog from the logic of your view-model, just like the first two approaches. But unlike the first, you do not need a service. Unlike the second, you do not need a handler. It's the most "data binding" way to do it, and likely what I would do.
FOUR 第四种方法是使用消息传递。消息传递是一个视图模型用来与另一个视图模型通信的机制。在这种情况下,您可以使用来自您的视图模型的消息传递(带有我们可能称为 ShowDialog 的消息),它被监听,而不是在另一个视图模型中,而是在您的页面中。这也可以正常工作。
The down side to this is that you need a messaging solution, but you might already have that. The up-side is that the logic for handling the visual could be relocated at any time as Messaging is multicasted to anyone listening.
如果我是你,我可能会首先考虑第 3 个。如果对您的应用场景没有更多的了解,我无法确定。不过,您是开发人员。所有这四个选项都很好。请确保不要被诱惑将 UIElement 传递到您的视图模型中。那是不必要的肮脏:)
祝你好运!