For the animation of UI elements like a progress bar, even in Microsofts documentation, there are always suggestions that (only) work from code behind, like this:
await progressBar.ProgressTo(0.75, 500, Easing.Linear);
I could not find a way to do this from a ViewModel, as it is not possible (and not intended) to access XAML elements from there. I tried to this with data binding, using BindableProperty. Could not get it to work. So, am I holding it wrong, or is it not possible?
I created a Drawable class:
public class ProgressArcDrawable : GraphicsView, IDrawable
{
public double ArcProgress
{
get => (double)GetValue(ArcProgressProperty);
set => SetValue(ArcProgressProperty, value);
}
public float Stroke
{
get => (float)GetValue(StrokeProperty);
set => SetValue(StrokeProperty, value);
}
public Color ArcColor
{
get => (Color)GetValue(ArcColorProperty);
set => SetValue(ArcColorProperty, value);
}
public static readonly BindableProperty ArcProgressProperty =
BindableProperty.Create(nameof(ArcProgress), typeof(double), typeof(ProgressArcDrawable));
public static readonly BindableProperty StrokeProperty =
BindableProperty.Create(nameof(Stroke), typeof(float), typeof(ProgressArcDrawable));
public static readonly BindableProperty ArcColorProperty =
BindableProperty.Create(nameof(ArcColor), typeof(Color), typeof(ProgressArcDrawable));
public void Draw(ICanvas canvas, RectF dirtyRect)
{
var endAngle = 90 - (int)Math.Round(ArcProgress * 360, MidpointRounding.AwayFromZero);
canvas.StrokeColor = ArcColor;
canvas.StrokeSize = Stroke;
canvas.DrawArc(Stroke / 2, Stroke / 2, (dirtyRect.Width - Stroke), (dirtyRect.Height - Stroke), 90, endAngle, false, false);
}
}
As I am using the MVVM toolkit, I created ObservableProperties in my viewmodel like so:
[ObservableProperty]
double arcProgress;
In my view I integrate the drawable with the data bindings:
<ContentPage.Resources>
<drawables:ProgressArcDrawable
x:Key="progressArcDrawable"
ArcProgress="{Binding ArcProgress}"
Stroke="20"
ArcColor="{Binding Scrum.ScrumTheme.AccentColor}" />
</ContentPage.Resources>
...
<Grid>
<GraphicsView
Drawable="{StaticResource progressArcDrawable}"
HeightRequest="350"
WidthRequest="350" />
</Grid>
The only binding that works, is the one that sets the stroke as a discrete value. The AccentColor binding works on other elements on the page, so there is data in there, but it does not work for the drawable. And thats the same for the ArcProgress, which should change the progress arc once a second.
Drawableinstance comes from aResourceDictionary.