Dynamically update Dockable Panel

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.

3 Likes