[Question] How to ensure a custom renderer does not generate a new element each time the view function is called (WPF)
BeardedPlatypus opened this issue · 2 comments
Heya, let me start off with thank you for creating Fabulous, I have been toying with it for the past few months and it has been an absolute blast.
I am not sure if this is the appropriate forum to post this, so if there is a better location, I'd be more than happy to move it to there.
Question / Discussion
For a small hobby project, I have created a small library on top of SDL2 and exposed this to .NET. I am using this to render code with SDL within a WPF application. I have created a Fabulous Xamarin.Forms WPF application in which I want to use this. I have written a really basic custom renderer to create the component within my application that uses this SDL2 view.
My problem is now, that each time I call my view function within my Fabulous code, a new control is created, which in turn creates a new WPF element. This is problematic as (in my current understanding) SDL2 binds its rendering to the window its contained in. When a new WPF element is created, the old window is thrown away and my SDL2 window needs to rebuild its complete state. While this would be technically possible, this is not the behaviour I want, instead I want to just update the view with the new state.
What I am trying to achieve now is that my custom renderer does not generate a complete new view, but reuses my old underlying view element, without instantiating a new element. For the life of me I cannot figure out how to do this, if someone could point me towards me some documentation on how to achieve this, I would be more than grateful.
I understand that having state associated with my view is not necessarily the best idea, and it might be well possible that using Fabulous Xamarin.Forms is just the wrong idea here, however I would like to build the majority of the user interface with Fabulous, and only do the actual specific rendering code within SDL2.
For reference, this is my current code:
- The fabulous application
- The underlying C++ SDL2 code
- The specific fabulous wrapping code
- The corresponding renderer
- The WPF component that is created in the renderer
- (edit) The view function in which the custom view element is called (last function in the file)
I have tried wrapping the viewport in a fix
function, as well as assigning it a key, neither has effect on the recreation of the view.
I hope this properly explains my problem I am having, if not I'd gladly provide additional details.
Thank you so much for your time!
@BeardedPlatypus Thank you for using Fabulous!
I'm not sure what's happening here.
Fabulous tries (relatively aggressively) to reuse existing elements as much as possible.
If your viewport is at the same place, with the same type (and you're not switching between viewport displayed, viewport removed), Fabulous will reuse it.
Your wrapping code is ok. Fabulous should reuse the element.
Could you tell me if in the debug output (usually in your IDE) you see a message telling that a new Viewport is created each time?
I don't know if OnElementChanged
behaves differently on WPF. If so, this is maybe where the viewport keeps getting recreated.
That, or a parent control keeps getting recreated, forcing all its children to get recreated as well.
@TimLariviere Thank you so much for your response
That, or a parent control keeps getting recreated, forcing all its children to get recreated as well.
I feel so dumb! I should have realised that I actually was recreating a parent.
After your comment, I went over my complete view code again, and further investigated with the help of the debug output.
Of course, it turns out I was doing something stupid. In my main view logic, I wanted to place an overlay when the project page was loading, which would darken my UI until it was ready. In order to do so, I, in my infinite wisdow, placed both the actual content, and the a boxview in a grid to create the overlay. This was triggered by single boolean, which determined whether I returned either the grid with both the content and the overlay, or just the content. Of course, this means that either I would have a grid as a parent of my viewport, or the content directly being the child of my content presenter.
I assume that this is the reason why the viewport was being recreated, especially given that removing this behaviour indeed fixes my problem!
I apologise for wasting your time with this! I do really appreciate your time and effort in responding, and for all the work you've done on Fabulous! Thank you again.
I'll go ahead and close this issue.