Sayo Komolafe
Sayo Komolafe

Reputation: 998

Activity Indicator before DisplayAlert

I have a content page that sends an email over an SMTP server in my Xamarin app.

On clicking the submit button to send the email, the app does nothing but waits. During this wait, I want to show an activity indicator or a Label of text loading, so the user knows something is working before showing a DisplayAlert that the process was successful.

For one reason or the other, the ActivityIndicator, and Label Text is not showing. Maybe am doing something wrong.

XAML

<StackLayout x:Name="myPop" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" 
            AbsoluteLayout.LayoutFlags="All" BackgroundColor="#C0808080" Padding="5">

    <ContentView x:Name="input_box_overlay" 
    AbsoluteLayout.LayoutBounds="0, 0, 1, 1" 
    AbsoluteLayout.LayoutFlags="All" 
    Padding="5">

        <StackLayout Padding="20" BackgroundColor="White" 
                     HorizontalOptions="Center" VerticalOptions="Center"
                     HeightRequest="230" WidthRequest="230">
            <Label Text="Enter suggestion" TextColor="Black" FontSize="Medium"/>

            <StackLayout Padding="0, 10, 0, 0">
                <Editor x:Name="user_text" HeightRequest="100" Keyboard="Chat" BackgroundColor="#f7f8f9"/>
            </StackLayout>

            <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
                <Label Text="Submitting..." x:Name="load"/>
                <ActivityIndicator x:Name="indicator"/>
            </StackLayout>

            <StackLayout Orientation="Horizontal" VerticalOptions="EndAndExpand" HorizontalOptions="CenterAndExpand">
                <Button TextColor="White" Text="Cancel" Clicked="Cancel_Clicked" BackgroundColor="#C0808080"/>
                <Button TextColor="White" Text="Submit" Clicked="Submit_Clicked" BackgroundColor="#395368" />
            </StackLayout>


        </StackLayout>
    </ContentView>

</StackLayout>

Code for the Submit_Clicked method/event

private async void Submit_Clicked(object sender, EventArgs e)
{
    try
    {
       indicator.IsRunning = true;
       indicator.IsVisible = true;
       indicator.IsEnabled = true;
       load.IsVisible = true;

        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("smtp.sendgrid.net");
        mail.From = new MailAddress("[email protected]");
        mail.To.Add("[email protected]");
        mail.Subject = "Subject";
        mail.Body = user_msg;
        SmtpServer.Port = 25;
        SmtpServer.Credentials = new NetworkCredential("username", "password");
        SmtpServer.EnableSsl = true;
        ServicePointManager.ServerCertificateValidationCallback = delegate (object sendemail, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        };
        SmtpServer.SendCompleted += (s, ev) => {
            indicator.IsRunning = false;
            indicator.IsVisible = false;
            indicator.IsEnabled = false;
            load.IsVisible = false;
        };
        SmtpServer.Send(mail);                        


        await DisplayAlert("Success", "Message Sent. Thank you.", "Ok");

        myPop.IsVisible = false;
        myPop.IsEnabled = false;
    }
    catch (Exception ex)
    {
        await DisplayAlert("Error", "Something went wrong. Please try again.", "ok");
        Console.WriteLine(ex.ToString());
    }
}

Upvotes: 1

Views: 687

Answers (1)

Nkosi
Nkosi

Reputation: 247088

Consider keeping the code async and not making it block the UI, which is what would happen with SmtpClient.Send

This is a refactoring of the original code provided to allow for a non-blocking flow

private async void Submit_Clicked(object sender, EventArgs e) {
    try {
        ToggleIndicator(true);
        await SendEmailAsync();
        ToggleIndicator(false);
        await DisplayAlert("Success", "Message Sent. Thank you.", "Ok");
        myPop.IsVisible = false;
        myPop.IsEnabled = false;
    } catch (Exception ex) {
        await DisplayAlert("Error", "Something went wrong. Please try again.", "ok");
        Console.WriteLine(ex.ToString());
    }
}

private void ToggleIndicator(bool show) {
    indicator.IsRunning = show;
    indicator.IsVisible = show;
    indicator.IsEnabled = show;
    load.IsVisible = show;
}

private async Task SendEmailAsync() {
    MailMessage mail = new MailMessage();
    mail.From = new MailAddress("[email protected]");
    mail.To.Add("[email protected]");
    mail.Subject = "Subject";
    mail.Body = user_msg;
    SmtpClient SmtpServer = new SmtpClient("smtp.sendgrid.net");
    SmtpServer.Port = 25;
    SmtpServer.Credentials = new NetworkCredential("username", "password");
    SmtpServer.EnableSsl = true;
    ServicePointManager.ServerCertificateValidationCallback = delegate (object sendemail, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) {
        return true;
    };
    await SmtpServer.SendMailAsync(mail);
}

While the XAML looks OK, I would also assume that the label and indicator visibility would be false initially

<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
    <Label Text="Submitting..." x:Name="load" IsVisible="False"/>
    <ActivityIndicator x:Name="indicator" IsVisible="False"/>
</StackLayout>

Upvotes: 3

Related Questions