Éder Rocha
Éder Rocha

Reputation: 1568

Xamarin ProgressBar binding Progress

The Progress property of my ProgressBar is updated by the method named UploadProgressCallback, invoked by UploadProgressChanged event. Everything is working but I noticed that ProgressBar goes directly from 0 to 1, it seems not have a smoothly update and I resolved to analyze the operation output and realized the division of sent bytes by the file size is being truncated to 0, so some results that should be 0.234 or 0.643, goes to Progress property as "0" and it causes bar keeps stuck on initial point, when upload is completed, the division will obviously return 1 and the bar is filled. I tried a lot of things but output is always 0. Does anyone have an advice that can fix that?

ProgressBar view on xaml

<ProgressBar IsVisible="{Binding UploadProgressVisibility}" IsEnabled="{Binding UploadProgressVisibility}" FlowDirection="LeftToRight" ProgressColor="Orange" Progress="{Binding UploadProgress}" Grid.Column="0" Grid.Row="1" HeightRequest="20" WidthRequest="80" Margin="0" />

UploadProgressCallback

webclient.UploadProgressChanged += new UploadProgressChangedEventHandler((s,e) => UploadProgressCallback(s,e,idrefecence));

private void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e, int idreference)
{
    double temp = (double) e.BytesSent / filesize;
    Device.BeginInvokeOnMainThread(() => 
    {
        valuesLock.EnterWriteLock();
        try
        {
           MyCollection[idreference].UploadProgress = temp;
           // this value is being bound to Progress property of ProgressBar 
        }
        finally { valuesLock.ExitWriteLock(); }
    });
}

also tried:

double temp = Convert.ToDouble((double)e.BytesSent / filesize, CultureInfo.InvariantCulture);

using this, I can obtain the correct result but decimal place separator is ',' not '.'

Upvotes: 0

Views: 624

Answers (2)

Jason
Jason

Reputation: 89092

an int divided by an int will return an int. You need to cast one of the values to a double first, then the division will return a double. The Convert is not needed

double temp = ((double)e.BytesSent) / filesize;

Upvotes: 1

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

Everything is working but I noticed that ProgressBar goes directly from 0 to 1, it seems not have a smoothly update

If you want to Progressbar update smoothly, I suggest you can use JimBobBennett.AnimatedProgress to implement animation.

Firstly, install JimBobBennett.AnimatedProgress by nuget package, then reference this dll in xaml.

Then use this Attached Properties for ProgressBar.

   <ProgressBar
            jbb:AttachedProperties.AnimatedProgress="{Binding Source={x:Reference entry1}, Path=Text}"
            jbb:AttachedProperties.AnimatedProgressAnimationTime="1000"
            jbb:AttachedProperties.AnimatedProgressEasing="BounceOut"
            ProgressColor="Red" />

        <Entry x:Name="entry1" />

The screenshot:

enter image description here

please take a look Attached Properties:

  public static class AttachedProperties
{
    public static BindableProperty AnimatedProgressProperty =
       BindableProperty.CreateAttached("AnimatedProgress",
       typeof(double),
       typeof(ProgressBar),
       0.0d,
       BindingMode.OneWay,
       propertyChanged: (b, o, n) => ProgressBarProgressChanged((ProgressBar)b, (double)n));

    public static BindableProperty AnimatedProgressAnimationTimeProperty =
       BindableProperty.CreateAttached("AnimatedProgressAnimationTime",
       typeof(int),
       typeof(ProgressBar),
       800,
       BindingMode.OneWay);

    public static BindableProperty AnimatedProgressEasingProperty =
       BindableProperty.CreateAttached("AnimatedProgressEasing",
       typeof(string),
       typeof(ProgressBar),
       default(string),
       BindingMode.OneWay);

    public static double GetAnimatedProgress(BindableObject target) => (double)target.GetValue(AnimatedProgressProperty);
    public static void SetAnimatedProgress(BindableObject target, double value) => target.SetValue(AnimatedProgressProperty, value);

    public static int GetAnimatedProgressAnimationTime(BindableObject target) => (int)target.GetValue(AnimatedProgressAnimationTimeProperty);
    public static void SetAnimatedProgressAnimationTime(BindableObject target, int value) => target.SetValue(AnimatedProgressAnimationTimeProperty, value);

    public static string GetAnimatedProgressEasing(BindableObject target) => (string)target.GetValue(AnimatedProgressEasingProperty);
    public static void SetAnimatedProgressEasing(BindableObject target, string value) => target.SetValue(AnimatedProgressEasingProperty, value);

    private static void ProgressBarProgressChanged(ProgressBar progressBar, double progress)
    {
        ViewExtensions.CancelAnimations(progressBar);

        var animationTime = GetAnimatedProgressAnimationTime(progressBar);
        var easingName = GetAnimatedProgressEasing(progressBar);

        progressBar.ProgressTo(progress, Convert.ToUInt32(Math.Max(0, animationTime)), GetEasing(easingName));
    }

    private static Easing GetEasing(string easingName)
    {
        if (easingName.ToUpper() == nameof(Easing.BounceIn).ToUpper())
            return Easing.BounceIn;
        if (easingName.ToUpper() == nameof(Easing.BounceOut).ToUpper())
            return Easing.BounceOut;
        if (easingName.ToUpper() == nameof(Easing.CubicIn).ToUpper())
            return Easing.CubicIn;
        if (easingName.ToUpper() == nameof(Easing.CubicOut).ToUpper())
            return Easing.CubicOut;
        if (easingName.ToUpper() == nameof(Easing.CubicInOut).ToUpper())
            return Easing.CubicInOut;
        if (easingName.ToUpper() == nameof(Easing.Linear).ToUpper())
            return Easing.Linear;
        if (easingName.ToUpper() == nameof(Easing.SinIn).ToUpper())
            return Easing.SinIn;
        if (easingName.ToUpper() == nameof(Easing.SinOut).ToUpper())
            return Easing.SinOut;
        if (easingName.ToUpper() == nameof(Easing.SinInOut).ToUpper())
            return Easing.SinInOut;
        if (easingName.ToUpper() == nameof(Easing.SpringIn).ToUpper())
            return Easing.SpringIn;
        if (easingName.ToUpper() == nameof(Easing.SpringOut).ToUpper())
            return Easing.SpringOut;

        return Easing.SinIn;
    }
}

Upvotes: 2

Related Questions