Добавить элемент на страницу XAML в то время как Task.Delay () - PullRequest
1 голос
/ 03 марта 2020

Я создаю приложение chatbot с чатами для входящих и исходящих сообщений. Для входящих сообщений я дал ему Task.Delay(), и теперь я хотел бы дать ему ActivityIndicator каждый раз, прежде чем всплывающее сообщение (т.е. я хочу показать индикатор активности, пока сообщение задерживается) , Я добавил индикатор активности в XAML элемента управления входящими сообщениями:
IncomingMessageItemControl

<ViewCell
    x:Class="BluePillApp.Controls.IncomingMessageItemControl"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:pancake="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
    mc:Ignorable="d">


    <Grid x:Name="Gridoo">
        <pancake:PancakeView
            Margin="10,10,80,10"
            Padding="15"
            BackgroundColor="#53ffc6"
            CornerRadius="20,20,0,20"
            HasShadow="False"
            HorizontalOptions="StartAndExpand">

            <Label
                FontSize="Medium"
                Text="{Binding Text}"
                TextColor="#1a1a1a" />
        </pancake:PancakeView>

        <ActivityIndicator IsRunning="True" IsVisible="True" />
    </Grid>
</ViewCell>

Проблема в том, что в ChatbotMessagingPage нажимается кнопка отправки, а затем исходящее сообщение отправляется до получения ответа / входящего сообщения, и я сделал это в MVVM следующим образом:
ChatbotMessagingPageViewModel

//This gets the chatbots response for each message
            chatbot.MainUser.ResponseReceived += async (sender, args) =>
            {
                await Task.Delay(1500);
                Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot });
            };
        }

        #region CLASS METHODS
        /// <summary>
        /// This function sends a message
        /// </summary>
        public void Send()
        {
            if (!string.IsNullOrEmpty(TextToSend))
            {
                var msgModel = new ChatMessageModel() { Text = TextToSend, User = App.User };

                //This adds a new message to the messages collection
                Messages.Add(msgModel);

                var result = chatbot.Evaluate(TextToSend);
                result.Invoke();

                //Removes the text in the Entry after message is sent
                TextToSend = string.Empty;
            }
        }

Каждый раз, когда я нажимаю кнопку отправки, появляется ActivityIndicator наряду с IncomingMessage я бы хотел, чтобы ActivityIndicator был первым, пока IncomingMessage откладывается.

1 Ответ

1 голос
/ 04 марта 2020

Я предполагаю, что эта ячейка представления является пузырем сообщения.

Когда вы делаете:

Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot });

Ваша коллекция обновляется, и ваш ListView или любой другой объект, содержащий эти ViewCelss, также обновляется. , ActivityIndicator является частью ViewCell, поэтому оно приходит одновременно с сообщением.

[ВАРИАНТ 1] Использование дополнительного флага

Что вы можно создать флаг IsBusy или IsDelay или что-то еще и связать с ним видимость ActivityIndicator и Label:

<Grid x:Name="Gridoo">
    <pancake:PancakeView
        Margin="10,10,80,10"
        Padding="15"
        BackgroundColor="#53ffc6"
        CornerRadius="20,20,0,20"
        HasShadow="False"
        HorizontalOptions="StartAndExpand">

        <Label
            FontSize="Medium"
            Text="{Binding Text}"
            TextColor="#1a1a1a"
            IsVisible="{Binding IsBusy, Converter={Helpers:InverseBoolConverter}}""> />
    </pancake:PancakeView>

    <ActivityIndicator x:Name="activityIndicator" IsRunning="True" IsVisible="{Binding IsBusy}" />
</Grid>

Обратите внимание, что я использовал IValueConverter для отрицания значения для этикетки. Если вы с ним не знакомы, отметьте this

Осталось добавить флаг в ваш ViewModel:

IsBusy = true; // this will make the activity indicator visible, but not the Label
// Also note that you first need to add the message
Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot }); 
await Task.Delay(1500);
IsBusy = false; // this will hige the activity indicator visible, and make Label visible

Так что в основном лог c следующее:

  1. Вы добавляете сообщение в свой чат, НО фактический текст скрыт, когда, с другой стороны, индикатор активности виден.
  2. Вы применяете delay
  3. Задержка заканчивается, вы меняете видимость обоих представлений.

Обратите внимание, что в моем примере я не объявил, где находится этот флаг, так как я не уверен, как остальные вашего кода выглядит так. Его можно добавить в ChatMessageModel или ChatMessageViewModel, так как вам потребуется флаг для каждого сообщения.

[ВАРИАНТ 2] в IncomingMessageItemControl.xaml.cs

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

Чтобы исправить это, вы можете переместить задержку в IncomingMessageItemControl.xaml.cs. Сначала вам нужно добавить x:Name и к индикатору активности, и к метке.

Затем вы можете сделать:

private async Task ChangeVisibilityAsync()
{
    Label.IsVisibe= false;
    ActivityIndicator.IsVisible = true;
    await Task.Delay(1500);
    Label.IsVisibe = true;
    ActivityIndicator.IsVisible = false;
}
...