You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am currently in the process of porting our WPF graph drawing library to Avalonia, and for the most part this has been fairly straightforward. However, a few issues did come up where I didn't immediately find an answer.
Our visual tree contains the whole graph visualization and – for various reasons – the tree is built mostly by ourselves and does not make use of typical WPF/Avalonia features that might come to mind where one would perhaps use an ItemsControl and just add all items to be visualized to its Items collection and let templating handle the rest. Effectively, we manage our own scene graph as a visual tree within the control.
Logical tree, containing our GraphControl
Visual tree, containing the template, along with item visualizations
In WPF this worked well, and for the most part it also does in Avalonia. However, some visualizations make use of Resources that are expected to be defined in the application or window. One particular example was that a TextBox we've shown for in-place editing worked, but was not visible since it wouldn't pick up its ControlTheme – lookless controls that are actually lookless in the UI make for not so great user experience ;-). Another is the button highlighted above, whose visual tree stopped at a ContentPresenter that was not able to puts the Panel in its Content into the visual tree as its Child.
As far as I understood it, resource/style lookup only works within the logical tree. However, the logical tree is also more or less expected to only contain the things that whoever created the window in XAML put there. Our control's template and all its children and the item visualizations should probably not be in the logical tree, at least when looked at in the Dev Tools. I've managed to figure out that even within the visual tree what gets applied by a template has the proper chain of Parents set, so effectively the logical tree still kind of continues into the visual tree, even though the parent's LogicalChildren collection is empty.
I've managed to make things work in a hacky way by casting certain controls to ISetLogicalParent and setting the parent. This obviously does feel like a hack. Something I've dabbled with yesterday, which seems promising and better supported was to ensure that our various container controls not only manage their VisualChildren collection, but also their LogicalChildren as needed. We kinda have to use VisualChildren since some visualizations use Visuals, not Controls (at least in WPF low-level drawing via Visuals has way less overhead, and it seems to me this still holds in Avalonia as well – basically a tradeoff between convenience in updating a visualization and rendering speed). So effectively, I'm now managing VisualChildren and, if an ILogical is added/removed, I also update LogicalChildren, which seems a bit backwards to how Avalonia typically works.
Is this basically a sane approach or am I way off here? I'll admit, we do things in WPF that may be sketchy, but happened to work, and writing custom controls with custom drawing is not terribly well-documented there, either. Chances are that it's not the most sensible approach we've chosen. But most parts of the Avalonia port were fairly easy with somewhat mechanical fixes, but in some places there seem to be major differences that could require major restructuring (I hope not, though).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
I am currently in the process of porting our WPF graph drawing library to Avalonia, and for the most part this has been fairly straightforward. However, a few issues did come up where I didn't immediately find an answer.
Our visual tree contains the whole graph visualization and – for various reasons – the tree is built mostly by ourselves and does not make use of typical WPF/Avalonia features that might come to mind where one would perhaps use an
ItemsControland just add all items to be visualized to its Items collection and let templating handle the rest. Effectively, we manage our own scene graph as a visual tree within the control.GraphControlIn WPF this worked well, and for the most part it also does in Avalonia. However, some visualizations make use of Resources that are expected to be defined in the application or window. One particular example was that a TextBox we've shown for in-place editing worked, but was not visible since it wouldn't pick up its
ControlTheme– lookless controls that are actually lookless in the UI make for not so great user experience ;-). Another is the button highlighted above, whose visual tree stopped at aContentPresenterthat was not able to puts the Panel in its Content into the visual tree as its Child.As far as I understood it, resource/style lookup only works within the logical tree. However, the logical tree is also more or less expected to only contain the things that whoever created the window in XAML put there. Our control's template and all its children and the item visualizations should probably not be in the logical tree, at least when looked at in the Dev Tools. I've managed to figure out that even within the visual tree what gets applied by a template has the proper chain of Parents set, so effectively the logical tree still kind of continues into the visual tree, even though the parent's
LogicalChildrencollection is empty.I've managed to make things work in a hacky way by casting certain controls to
ISetLogicalParentand setting the parent. This obviously does feel like a hack. Something I've dabbled with yesterday, which seems promising and better supported was to ensure that our various container controls not only manage theirVisualChildrencollection, but also theirLogicalChildrenas needed. We kinda have to useVisualChildrensince some visualizations useVisuals, notControls (at least in WPF low-level drawing via Visuals has way less overhead, and it seems to me this still holds in Avalonia as well – basically a tradeoff between convenience in updating a visualization and rendering speed). So effectively, I'm now managingVisualChildrenand, if anILogicalis added/removed, I also updateLogicalChildren, which seems a bit backwards to how Avalonia typically works.Is this basically a sane approach or am I way off here? I'll admit, we do things in WPF that may be sketchy, but happened to work, and writing custom controls with custom drawing is not terribly well-documented there, either. Chances are that it's not the most sensible approach we've chosen. But most parts of the Avalonia port were fairly easy with somewhat mechanical fixes, but in some places there seem to be major differences that could require major restructuring (I hope not, though).
Beta Was this translation helpful? Give feedback.
All reactions