Forum Xamarin.Forms

Creating badgeview using skiasharp. But value doesnot updates

ParamjitSinghParamjitSingh USMember ✭✭
edited December 2019 in Xamarin.Forms

I am working on a shopping app. I am using shell. I created a badgeview using skiasharp. Now I want to increase and decrease the value of badge view as per user actions. But the user actions does not propogate any changes on the UI. My XAML file is -

`
<ContentPage.BindingContext>

</ContentPage.BindingContext>

<Shell.TitleView>


</Shell.TitleView>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
        <Button Text="-" FontSize="Large" Padding="0" Command="{Binding DecrementCommand}" CommandParameter="FirstControl"></Button>
        <Label Text="{Binding FirstControlCount, StringFormat='{0}'}" VerticalOptions="Center"></Label>
        <Button Text="+" FontSize="Large" Padding="0" Command="{Binding IncrementCommand}" CommandParameter="FirstControl"></Button>
    </StackLayout>

     <StackLayout Grid.Row="1" Orientation="Horizontal" HorizontalOptions="Center">
        <Button Text="-" FontSize="Large" Padding="0" Command="{Binding DecrementCommand}" CommandParameter="SecondControl"></Button>
        <Label Text="{Binding SecondControlCount, StringFormat='{0}'}" VerticalOptions="Center"></Label>
        <Button Text="+" FontSize="Large" Padding="0" Command="{Binding IncrementCommand}" CommandParameter="SecondControl"></Button>
    </StackLayout>
</Grid>

`

The ViewModel class is -

`using System;
using System.Threading.Tasks;
using System.Windows.Input;
using ReactiveUI.Fody.Helpers;
using Xamarin.Forms;

namespace BadgeSkiaSample.ViewModels
{
public class MainViewModel
{
public ICommand IncrementCommand { get; set; }
public ICommand DecrementCommand { get; set; }

    [Reactive]
    public int FirstControlCount { get; set; }
    [Reactive]
    public int SecondControlCount { get; set; }
    [Reactive]
    public int TotalCount => FirstControlCount + SecondControlCount;

    public MainViewModel()
    {
        IncrementCommand = new Command<string>( (parameter)=> IncreaseCount(parameter));
        DecrementCommand = new Command<string>((parameter)=>  DecreaseCount(parameter));
    }

    private void DecreaseCount(string parameter)
    {
        if (parameter == "FirstControl")
        {
            --FirstControlCount;
            return;
        }

        --SecondControlCount;
    }

    private void IncreaseCount(string parameter)
    {
        if (parameter == "FirstControl")
        {
          FirstControlCount++;
            return;
        }

        ++SecondControlCount;

    }
}

}`

Finally the BadgeView is defined in separate class-

`using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
using ReactiveUI.Fody.Helpers;

namespace BadgeSkiaSample.Controls
{
public class BadgeView : SKCanvasView
{
public static readonly BindableProperty BadgeColorProperty = BindableProperty.Create(nameof(BadgeColor), typeof(SKColor), typeof(BadgeView), SKColors.Red);
public static readonly BindableProperty TextColorProperty = BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(BadgeView), SKColors.White);
public static readonly BindableProperty BadgeValueProperty = BindableProperty.Create(nameof(BadgeValue), typeof(int), typeof(BadgeView), 0, defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnBadgeValueChanged);

    private static void OnBadgeValueChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var view = bindable as BadgeView;
        view?.InvalidateSurface();

    }

    [Reactive]
    public SKColor BadgeColor
    {
        get => (SKColor)GetValue(BadgeColorProperty);
        set => SetValue(BadgeColorProperty, value);
    }

    [Reactive]
    public SKColor TextColor
    {
        get => (SKColor)GetValue(TextColorProperty);
        set => SetValue(TextColorProperty, value);
    }

    [Reactive]
    public int BadgeValue
    {
        get => (int)GetValue(BadgeValueProperty);
        set => SetValue(BadgeValueProperty, value);
    }



    SKPaint textPaint = new SKPaint
    {
        TextSize = 18,
        IsAntialias = true,
        Color = SKColors.White,

    };


    SKPaint circleFillPaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = (Color.FromHex("#E96125")).ToSKColor(),
        IsAntialias = true
    };

    public BadgeView()
    {
        BindingContext = this;
        this.WidthRequest = 15;
        this.HeightRequest = 15;
    }

    protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
    {
        SKCanvas canvas = e.Surface.Canvas;
        canvas.Clear(SKColors.Yellow);
        canvas.DrawCircle((float)(this.Width), (float)this.Height, 15, circleFillPaint);
        canvas.DrawText(BadgeValue.ToString(), 6, 20, textPaint);
    }
}

}`

Please find attached the project file.

Best Answer

Answers

  • ParamjitSinghParamjitSingh USMember ✭✭

    For some unknown reason the BindingContext and TitleView code is not visible in the question-

     <ContentPage.BindingContext>
            <viewmodels:MainViewModel/>
        </ContentPage.BindingContext>
    
         <Shell.TitleView>
               <StackLayout VerticalOptions="Center">
                   <controls:BadgeView  BadgeValue="{Binding TotalCount,StringFormat='{0}'}"  HorizontalOptions="Center"></controls:BadgeView>
                   <Label Text="Badge" HorizontalOptions="Center"/>
               </StackLayout>
    
           </Shell.TitleView>
    
  • JarvanJarvan Member, Xamarin Team Xamurai

    Try to use Syncfusion.Xamarin.SfBadgeView plugin to add the badges. Binding the BadgeText property to update the values.

    <badge:SfBadgeView HorizontalOptions="Center" VerticalOptions="Center" BadgeText="20">
            <badge:SfBadgeView.Content>
                <Button Text="Primary" WidthRequest="120"  HeightRequest="60"/>
            </badge:SfBadgeView.Content>
    </badge:SfBadgeView>
    

    Check the Tutorial:
    https://help.syncfusion.com/xamarin/badge-view/getting-started

  • ParamjitSinghParamjitSingh USMember ✭✭
    edited December 2019

    @Jarvan Thanks for pointing out the cause of the issue. Actually the Reactive attribute is for Notifying property Changed. But I need to use the base class ReactiveObject for that functionality. After using ReactiveObject as base class the Properties are now notifying changes.

    Syncfusion control is a good option. But I still want to implement my own. But can't use ReactiveObject in BadgeView class as it is already derived from SKCanvasView. Any Suggestions.

Sign In or Register to comment.