Custom Binding firing after OnPaintSurface event

EdiporeiEdiporei BRMember ✭✭

Hi!

I'm currenly facing an issue with my drawing setup. I use SkiaSharp as my drawing canvas, which I have overriden the OnPaintSurface to make my drawings based on the ViewModel. Everything works fine, except that the OnPaintSurface method is firing before the custom bindings that I've made to pull the data from the ViewModel. Therefore, this causes the data to be sort of delayed, because when the OnPaintSurface fires the data from the ViewModel hasn't reached the class yet.

I activate the OnPaintSurface() with an event, like this:

`

void ItemSelecionado (object sender, Syncfusion.ListView.XForms.ItemTappedEventArgs e)
    {
        nvd_Opções.ToggleDrawer();
        gcd_Cálculo.InvalidateSurface();
    }

`

It's after this event that everything works. The bindings fire as well as the OnPaintSurface(). The SkiaSharp class I've written is shown below.

`

public class GeoCálculoDesenho : SKCanvasView
{

//This is used on the OnPaintSurface method and is fed by the ViewModel via the custom bindable properties just below
    public List<ModelB> ListaB = new List<ModelB>();
    public List<ModelC> ListaC = new List<ModelC>();

    public static readonly BindableProperty DataSelecionadaProperty = BindableProperty.Create(
        propertyName: "DataSelecionada",
        returnType: typeof(ModelA),
        declaringType: typeof(GeoCálculoDesenho),
        defaultValue: null,
        defaultBindingMode: BindingMode.OneWay,
        propertyChanged: DataSelecionadaChanged
        );
    public SondagemModel DataSelecionada
    {
        get { return (ModelA)GetValue(DataSelecionadaProperty); }
        set { SetValue(DataSelecionadaProperty, value); }
    }
    async private static void DataSelecionadaChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var control = (GeoCálculoDesenho)bindable;
        if ((Model0)newvalue != null)
        {
            control.ListaB = await App.BancoData.GetModelBAsync(((ModelA)newvalue).ID);
            control.ListaC = await App.BancoData.GetModelCAsync(((ModelA)newvalue).ID);
        }
        else
        {
            control.ListaB = new List<ModelB>();
            control.ListaC = new List<ModelC>();
        }

    }



    public GeoCálculoDesenho()
    {

    }

    protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
    {
        base.OnPaintSurface(e);

        //Here comes the drawing code using the ListaB and ListaC as data from the ViewModel

    }

}

`

On the Xaml, I simply bind the data like this:

`

<local:GeoCálculoDesenho DataSelecionada="{Binding geo_Data}"/>

`

On my ViewModel:

`

    public ModelA _data;
    public ModelA geo_Data
    {
        get { return _data; }
        set
        {
            _data = value;
            OnPropertyChanged("geo_Data");
        }
    }

`

Everything works properly, but the order in which things happen is being problematic. I can't grasp why exactly is the OnPaintSurface method being fired before the DataSelecionada Binding. Is it some concept about custom bindable properties that I ended up missing? Any light on this matter would be really helpful!

PS.: I avoided cluttering the post with unnecessary code, so I've put only what I deemed necessary to help everyone grasp the situation properly. If you think I might've missed something important, just ask and I'll happily reply it.

Best Answer

  • EdiporeiEdiporei BRMember ✭✭
    Accepted Answer

    I ended up finding a solution. Instead of calling the OnPaintSurface method on the event, I put it on the setting code of the custom bindable property, like this:

    `

    public ModelA DataSelecionada
        {
            get { return (ModelA)GetValue(DataSelecionadaProperty); }
            set { SetValue(DataSelecionadaProperty, value); InvalidateSurface(); }
        }
    

    `

    With this, everytime the DataModel on the ViewModel changes (and only after that), the OnPaintSurface is called. Now, the codes are working in the proper order.

    I ended up answering my own question, but at least I hope this serves to anyone...

Answers

  • EdiporeiEdiporei BRMember ✭✭
    Accepted Answer

    I ended up finding a solution. Instead of calling the OnPaintSurface method on the event, I put it on the setting code of the custom bindable property, like this:

    `

    public ModelA DataSelecionada
        {
            get { return (ModelA)GetValue(DataSelecionadaProperty); }
            set { SetValue(DataSelecionadaProperty, value); InvalidateSurface(); }
        }
    

    `

    With this, everytime the DataModel on the ViewModel changes (and only after that), the OnPaintSurface is called. Now, the codes are working in the proper order.

    I ended up answering my own question, but at least I hope this serves to anyone...

Sign In or Register to comment.