Только один ContentDialog может быть открыт в любое время - PullRequest
0 голосов
/ 23 мая 2018

Если я нажимаю кнопку входа в систему несколько раз, появляется сообщение: «Асинхронная операция не была правильно запущена. В любой момент может быть открыт только один ContentDialog».(Задержка служит для представления времени, которое требуется приложению для обращения к серверу, чтобы узнать, действителен ли пользователь.)

Если я использую MessageDialog, все работает нормально, но я хочу использовать дополнительную настройку, котораяContentDialog предоставляет.

Эта ссылка не помогла.Мой пример кода ниже показывает, как я пытаюсь его использовать.

XAML:

<Page
    x:Class="DuckTracker.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DuckTracker"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Height="20">Name:</TextBlock>
    <TextBox Grid.Row="0" Grid.Column="1" Height="20"></TextBox>
    <Button Click="Button_Click" Grid.Row="2" VerticalAlignment="Bottom">Login</Button>
    </Grid>
</Page>

Код позади:

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace DuckTracker
{

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            bool canLogin = await CanLogin(); 

            if (canLogin == false)
            {
                try
                {
                     await AlertWithMessages("Fail", "Could not log in!", "ok");

                }
                catch (Exception ex)
                {

                    var dialog = new Windows.UI.Popups.MessageDialog(ex.Message, "Error");
                    await dialog.ShowAsync();
                }

            }
        }

        public async Task AlertWithMessages(string title, string msg, string confirm)
        {
            ContentDialog dialog = new ContentDialog()
            {
                Title = title,
                Content = msg,
                PrimaryButtonText = confirm
            };

            await ContentDialogMaker.CreateContentDialogAsync(dialog, true);

        }

        public async Task<bool> CanLogin()
        {
            await Task.Delay(1000);

            return false;
        }
    }
}

Код заимствован из ссылки, упомянутой выше:

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;

namespace DuckTracker
{
    public static class ContentDialogMaker
    {
        public static async void CreateContentDialog(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); }
        public static async Task CreateContentDialogAsync(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); }

        static async Task CreateDialog(ContentDialog Dialog, bool awaitPreviousDialog)
        {
            if (ActiveDialog != null)
            {
                if (awaitPreviousDialog)
                {
                    await DialogAwaiter.Task;
                    DialogAwaiter = new TaskCompletionSource<bool>();
                }
                else ActiveDialog.Hide();
            }
            ActiveDialog = Dialog;
            ActiveDialog.Closed += ActiveDialog_Closed;
            await ActiveDialog.ShowAsync();
            ActiveDialog.Closed -= ActiveDialog_Closed;
        }

        public static ContentDialog ActiveDialog;
        static TaskCompletionSource<bool> DialogAwaiter = new TaskCompletionSource<bool>();
        private static void ActiveDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args) { DialogAwaiter.SetResult(true); }
    }
}

Я добавил DoingStuff для Button_Click (), которая предотвращает сообщение об ошибке, но я думаю, что должен быть лучший способ:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    if (DoingStuff == false)
    {
        DoingStuff = true;

        bool canLogin = await CanLogin();

        if (canLogin == false)
        {
            try
            {

                await AlertWithMessages("Fail", "Could not log in!", "ok");

            }
            catch (Exception ex)
            {

                var dialog = new Windows.UI.Popups.MessageDialog(ex.Message, "Error");
                await dialog.ShowAsync();
            }

        }

        DoingStuff = false;
    }
}

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

Попробуйте, прежде чем открыть следующий диалог.

ContentDialogMaker.ActiveDialog?.Hide();
// Show new Dialog here.
0 голосов
/ 24 мая 2018

В общем, когда вы запускаете метод входа в систему, вам нужно одновременно включить кнопку входа в систему, чтобы избежать многократного щелчка.И ваше решение также доступно, что кнопка не будет работать, пока предыдущий диалог не показал.

И я создал новый ContentDialogMaker.Для получения дополнительной информации вы можете обратиться к следующему:

public static class ContentDialogMaker
{
    public static async void CreateContentDialog(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); }
    public static async Task CreateContentDialogAsync(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); }

    static async Task CreateDialog(ContentDialog Dialog, bool awaitPreviousDialog)
    {
        if (ActiveDialog != null)
        {
            if (awaitPreviousDialog)
            {
                ActiveDialog.Hide();
            }
            else
            {
                switch (Info.Status)
                {
                    case AsyncStatus.Started:
                        Info.Cancel();
                        break;
                    case AsyncStatus.Completed:
                        Info.Close();
                        break;
                    case AsyncStatus.Error:

                        break;
                    case AsyncStatus.Canceled:

                        break;
                }
            }
        }
        ActiveDialog = Dialog;
        ActiveDialog.Closing += ActiveDialog_Closing;
        Info = ActiveDialog.ShowAsync();
    }
    public static IAsyncInfo Info;
    private static void ActiveDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
    {
        ActiveDialog = null;
    }

    public static ContentDialog ActiveDialog;
}

Единственное отличие состоит в том, что ActiveDialog был очищен в методе обработки события ActiveDialog_Closing.И он может быть уверен, что предыдущий диалог будет очищен после отображения.Таким образом, только один ContentDialog будет открыт одновременно.

0 голосов
/ 23 мая 2018

Отключить кнопку во время обработки клика.

private async void Button_Click(object sender, RoutedEventArgs e)
{
    if (sender is Button button)
    {
        button.IsEnabled = false;
    }

    … handle button click

    if (sender is Button button2)
    {
        button2.IsEnabled = true;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...