question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ICustomDrawOperation.Render not being called after DrawingContext.Custom call

See original GitHub issue

Describe the bug When implementing a custom draw operation via ICustomDrawOperation, its Render method isn’t always invoked when the associated control calls DrawingContext.Custom.

Minimal Issue Reproduction

public class SkiaCanvas : UserControl
{
    private class SkiaCallbackRenderOperation : ICustomDrawOperation
    {
        public Action<SKCanvas>? RenderCall;
        public Rect Bounds { get; set; }

        public void Dispose()
        {
        }

        public bool Equals(ICustomDrawOperation? other)
        {
            return false;
        }

        public bool HitTest(Point p)
        {
            return false;
        }

        public void Render(ImmediateDrawingContext context)
        {
            // This method is reached only when resizing the window or opening a menuitem over the control
            // No calls from Render, invoked via custom.Render reach this
            if (!context.TryGetFeature<ISkiaSharpApiLeaseFeature>(out var leaseFeature))
                throw new Exception("SkiaSharp is not supported.");

            using var lease = leaseFeature.Lease();

            RenderCall?.Invoke(lease.SkCanvas);
        }
    }

    public event Action<SkiaRenderEventArgs>? RenderSkia;
    private readonly SkiaCallbackRenderOperation _skiaCallbackRenderOperation;

    public SkiaCanvas()
    {
        _skiaCallbackRenderOperation = new SkiaCallbackRenderOperation
        {
            RenderCall = canvas =>
            {
                RenderSkia?.Invoke(new SkiaRenderEventArgs
                {
                    Sender = this,
                    Canvas = canvas
                });
            }
        };
        ClipToBounds = true;
    }


    public override void Render(DrawingContext context)
    {
        // This method (Render) is called at refresh rate, everything is fine

        _skiaCallbackRenderOperation.Bounds = new Rect(0, 0, DesiredSize.Width, DesiredSize.Height);

        // Jump into SkiaCallbackRenderOperation.Render
        context.Custom(_skiaCallbackRenderOperation);

        Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
    }
}

Expected behavior ICustomDrawOperation.Render is executed when calling DrawingContext.Custom

Issue Analytics

  • State:closed
  • Created 2 months ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
beto-rodriguezcommented, Jul 18, 2023

The render method will be called while the control is Invalid, Avalonia will call (or invalidate) the Render method for you when the size changes or the first time the control needs to render, then it is your responsibility to call the InvalidateVisual(); method to let Avalonia know that that control needs to be redrawn.

0reactions
maxkatz6commented, Jul 20, 2023

I have run your code locally, and Bounds was not empty. Moreover, Bounds in general is a property you usually need to read when you want to get the current size of the control. As with any other control, actual bounds of the control depend on the parent panel (Grid, StackPanel, Canvas…they all will allocate size for a child differently) and control properties (Alignment, Min/MaxWidth/Height…)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Custom Avalonia controll to render from other thread ...
I have a background thread, which renders some image to WriteableBitmap. I'm making a custom control, which will use this writeablebitmap and ...
Read more >
ISkiaSharpApiLeaseFeature.. Where is it? : r/AvaloniaUI
I'm having trouble with some drawing code I got from stackexchange which is for a SKCanvas drawing class. It no longer works and...
Read more >
Upgrading from 0.10
Do NOT remove the call to InitializeComponent() in the constructor: this method is now a generated method and still needs to be called;...
Read more >
UIElement.OnRender(DrawingContext) Method
The OnRender(DrawingContext) method can be overridden to add further graphical elements (not previously defined in a logical tree) to a rendered element, such ......
Read more >
Avalonia graph control. In the MainWindowViewModel. Scroll up
300" I set up my view like this: Occurs when the control or its child control loses the pointer capture for any reason,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found