UWP ContentDialog Invocation

Я использую UWP и Template 10 для создания приложения с графическим интерфейсом, следуя шаблону MVVM. Как часть приложения мне нужно вызвать диалог содержимого, нажав кнопку на главной странице. Поэтому для этой цели был создан отдельный ContentDialog в отдельном файле.xaml:

<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>

Как правильно открыть / вызвать его на моей главной странице, нажав кнопку (так как мне нужно разделить логику для представления и модели представления)?

Как я это делаю сейчас:

На главной странице я вызываю 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 для меня. Не могли бы вы помочь мне сделать это правильно?

РЕДАКТИРОВАТЬ:

Я реализовал сервис диалога и внедрил его в модель основного вида. Однако я получил еще одно препятствие. Для этого диалога я создал отдельную модель представления и свойство, которое инкапсулирует значение текстового поля диалога. Когда я нажимаю кнопку "принять" в диалоговом окне - мне нужно, чтобы это значение было отражено в моем главном окне. Поэтому мне нужно передать значение текстового поля диалога из модели вида диалога в модель основного вида. Должен ли я выполнить еще одно внедрение зависимости, чтобы справиться с этим?

2 ответа

Решение

У вас есть четыре варианта.

ОДИН Первый - это сервис, как объясняет @Ask-too-much. На самом деле, это прекрасное решение, если вам это нравится.

Преимущества первого решения заключаются в том, что его можно использовать повторно. Если вы не используете этот пользовательский интерфейс повторно, то, честно говоря, выделенная служба может оказаться излишней.

ВТОРОЕ Второе - это модельное событие. То есть ваша страница может подписаться на событие вашей модели представления (назовем его ShowContentDialog), и когда оно вызывается моделью представления, ваша страница обрабатывает его представление.

Преимущества этого подхода в том, что, как и в первом подходе, вы перекладываете усилия на другой класс. В этом случае вы создаете одноразовое решение, не требуя службы, интерфейса службы или внедрения этой службы каким-либо образом. Если вы не ждете результатов мероприятия, то я думаю, что это идея для 99% вопросов, подобных вашей.

Третий Третий подход заключается в использовании другого элемента управления, который может быть привязан к свойству. Например, поскольку вы уже используете Шаблон 10, вы можете использовать элемент управления ModalDialog, который имеет свойство IsModal. Свойство в вашей view-модели (назовем его IsModalVisible) можно использовать для управления диалогом без привязки к нему.

Хорошая часть этого в том, что вы получаете возможность вызывать диалог из логики вашей модели представления, как и первые два подхода. Но в отличие от первого, вам не нужен сервис. В отличие от второго, вам не нужен обработчик. Это самый "привязанный к данным" способ сделать это, и, вероятно, то, что я бы сделал.

ЧЕТВЕРТЫЙ Четвертый способ сделать это - использовать обмен сообщениями. Обмен сообщениями - это механизм, который одна модель представления использует для связи с другим. В этом случае вы можете использовать сообщения из вашей модели представления (с сообщением, которое мы могли бы назвать ShowDialog), который прослушивается не в другой модели представления, а на вашей странице. Это тоже будет работать нормально.

Недостатком является то, что вам нужно решение для обмена сообщениями, но у вас уже может быть это. Положительным моментом является то, что логика обработки визуала может быть перемещена в любое время, так как обмен сообщениями многоадресно передается любому слушающему.

Если бы я был тобой, я бы сначала рассмотрел номер 3, возможно. Без большего понимания сценария вашего приложения, я не могу быть уверен. Вы разработчик, хотя. Все четыре варианта хороши. Только будьте уверены, что вы не захотите передать UIElement в вашу модель представления. Это ненужная гадость:)

Удачи!

Предлагаемое решение в MVVM - не создавать экземпляр Speech Dialog непосредственно в ViewModel, создать 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();
    }
}
Другие вопросы по тегам