Skip to content

Proposal: UIElement/FrameworkElement should expose protected method to add/initialize VisualTree #5530

@michael-hawker

Description

@michael-hawker

Proposal: UIElement/FrameworkElement should expose protected method to add/initialize VisualTree

Follow-up from discussion on docs repo here: MicrosoftDocs/winrt-api#646

Summary

Currently, especially in C#, it's not possible to inherit directly from FrameworkElement for a low-level component. Even in WinUI 2 with C++ here, while they look like they're inheriting from FrameworkElement, they're really using Panel (see DeriveFromPanelHelper_base) as an intermediary even if only a single child is expected.

The ability to initialize a Child or Children property into the Visual Tree that's being created on a subclass of FrameworkElement is not exposed even as a protected member within the framework. This means that while you can write code that inherits directly from FrameworkElement, there's no way to get it to render as it can't be added to the VisualTree itself.

Rationale

In the Windows Community Toolkit, we wanted to add a low-level component akin to Viewbox for constraining to a specific aspect ratio. It made sense to make it a single-child control from FrameworkElement, but we can't do that directly as we can't add the Child property we create to the Visual Tree. See CommunityToolkit/WindowsCommunityToolkit#4104.

Instead we need to inherit from Panel if we want something simple, but then that allows for multiple children to be added (which is odd for this scenario) OR we need to inherit from ContentPresenter which does more than we need it to do with templating support.

  • Would allow library developers to also develop lower-level components without the overhead of the high-level abstractions.

Scope

Capability Priority
This proposal will allow developers to accomplish initialize and render a low-level UI component Must
This proposal will allow end users to accomplish react to remove and replace content when a developer changes the content of the sub-classed control Must
This proposal will allow developers to create an element which accepts multiple children Could

API Proposal

Example of what a proposed API could look like with a protected AddChild and RemoveChild method for UIElement:

  public MyClass : FrameworkElement
  {
      propdp UIElement Child; // Shorthand
      
      private static void ChildPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {      
          if (d is FrameworkElement element && e.OldValue != e.NewValue)
          {
             element.RemoveChild(e.OldValue); // new protected method
             
             if (e.NewValue != null)
             {
                 element.AddChild(e.NewValue); // new protected method
             }
          }
      }
 }

Open Questions

  • I think it makes sense by default that a FrameworkElement would have a single child as a root for folks to subclass from. Otherwise if they accept multiple-children, it feels like they'd be a Panel based implementation at that point? I don't know the implementation details of Panel so not sure where it makes sense to optimize for the single vs. multi-children support in the stack.
  • I noticed some controls like ParallaxView expose Child as a Dependency Property, but others like Border do not. Is there a reason? Is it required to be a DP to support removing/adding dynamically to the content of the control?
  • There's also the ChildTransitions property on many FrameworkElement subclasses, there'd probably at least need to be documentation on how to add that into this scenario as well.
  • WPF had the Decorator subclass as a mirror to Panel but that took a single child. Does it make sense to provide that as a new base for Border/Viewbox like it was in WPF and keep more of the abstraction, but provide a lighter-weight model to build off-of.
  • Should Viewbox be ViewBox??? 😋

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature proposalNew feature proposalneeds-winui-3Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3)product-winui3WinUI 3 issuesteam-ControlsIssue for the Controls teamwct

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions