You are right, I was superficial. I compared the DockablePanel inplementation in pyrevit with my previous addin using dockable panels, and it was slightly different. The WPF panel was a sub-class of Page AND IDockablePaneProvider and the SetupDuckablePane() method was defined in it. If I have time i might try to make a PR but in the meanwhile you could implement your own WPFPanel class and register function using the ones provided in pyrevit as a template, but with the modifications I mentioned above.
As a minimal modification on tha pyrevit.forms module you could try:
class _WPFPanelProvider(UI.IDockablePaneProvider):
"""Internal Panel provider for panels"""
def __init__(self, panel_type, default_visible=True):
self._panel_type = panel_type
self._default_visible = default_visible
# this is added:
self.panel = self._panel_type()
def SetupDockablePane(self, data):
"""Setup forms.WPFPanel set on this instance"""
# TODO: need to implement panel data
# https://apidocs.co/apps/revit/2021.1/98157ec2-ab26-6ab7-2933-d1b4160ba2b8.htm
# instead of this:
# data.FrameworkElement = self._panel_type()
# try this:
data.FrameworkElement = self.panel
data.VisibleByDefault = self._default_visible
def register_dockable_panel(panel_type, default_visible=True):
"""Register dockable panel
Args:
panel_type (forms.WPFPanel): dockable panel type
default_visible (bool, optional):
whether panel should be visible by default
"""
if not issubclass(panel_type, WPFPanel):
raise PyRevitException(
"Dockable pane must be a subclass of forms.WPFPanel"
)
panel_uuid = coreutils.Guid.Parse(panel_type.panel_id)
dockable_panel_id = UI.DockablePaneId(panel_uuid)
# this is added:
panel_provider = _WPFPanelProvider(panel_type, default_visible)
HOST_APP.uiapp.RegisterDockablePane(
dockable_panel_id,
panel_type.panel_title,
# instead of this:
# _WPFPanelProvider(panel_type, default_visible)
# try this:
panel_provider
)
# this is added:
return panel_provider.panel
Hope this helps.