【问题标题】:Add element to XAML page whiles in Task.Delay()在 Task.Delay() 中将元素添加到 XAML 页面
【发布时间】:2020-06-15 07:27:49
【问题描述】:

我正在构建一个聊天机器人应用程序,其中包含用于传入和传出消息的聊天气泡。对于传入的消息,我给了它一个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;
            }
        }

每次我按下发送按钮时,ActivityIndi​​cator 都会与 IncomingMessage 一起出现,我希望 ActivityIndi​​cator 先出现,而 IncomingMessage 被延迟。

【问题讨论】:

  • 既然你已经得到消息,那么延迟添加消息是没有意义的,而是延迟元素的呈现。你可以做褪色动画 - Xamarin Forms Animation documentation
  • 我不想延迟添加消息。每条消息在显示之前都有一个延迟,我想要的是在延迟时弹出一个活动指示器
  • 那么你应该有一个不同的策略......将忙碌光标放在列表的页脚,等待消息时显示......简单,让我知道你是否需要更多帮助

标签: asynchronous xamarin.forms task


【解决方案1】:

我猜那个视图单元格就是消息气泡。

当你这样做时:

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

您的收藏已更新,您的 ListView 或任何持有这些 ViewCelss 的东西也已更新。 ActivityIndicatorViewCell 的一部分,因此它与消息同时出现。

[选项 1] 使用附加标志

您可以做的是创建一个标志IsBusyIsDelay 或其他东西并将ActivityIndi​​cator 和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

所以基本上逻辑如下:

  1. 您将消息添加到聊天中,但实际文本是隐藏的,而活动指示器是可见的。
  2. 您应用延迟
  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;
}

【讨论】:

    猜你喜欢
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-17
    • 2012-09-19
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    相关资源
    最近更新 更多