Rhinoceros 8 WPF load issue

Hi,

I’m trying to create new WPF plugin in Rhinoceros 8 however I’m getting error saying, that “The panel type must have a constructor with a uint, RhinoDoc or no parameters”. The thing is I do have uint in my panel host. This is how my host looks like


        /// <summary>
        /// Rhino framework requires a System.Windows.Forms.IWin32Window derived object for a panel.
        /// </summary>
        [System.Runtime.InteropServices.Guid("...")]
        public class NewPanelHost : RhinoWindows.Controls.WpfElementHost
        {
            //WPFInteropPanelBase
            public NewPanelHost(uint docsn)
              : base(new NewPanel(docsn), null) // No view model (for this example)
            {
                InitializePanel();
            }

            void InitializePanel()
            {
                var panel_id = NewPanel.PanelId;
                var panel_visible = Panels.IsPanelVisible(panel_id);

                var type = typeof(NewPanel);
                if (panel_visible == false)
                    Panels.OpenPanel(type.GUID);
            }

            /// <summary>
            /// Returns the ID of this panel.
            /// </summary>
            public static System.Guid PanelId
            {
                get
                {
                    return typeof(NewPanelHost).GUID;
                }
            }
        }

So what could be wrong?

Hi @karol.wierzbicki,

Does adding a constructor that take a RhinoDoc parameter make a difference?

– Dale

Hi,

It’s the same with RhinoDoc. This code is part of bigger project, could this matter?

Hi @karol.wierzbicki,

Can you provide me a cheap sample, that I run here?

Thanks,

— Dale

Can you post this class for reference? NewPanel

Hi,

I’m comming back to the topic as I had no time before to take care of it. this is sample of the code:

public partial class HcmPlugIn : PlugIn
{
   
    public HcmPlugIn()
    {
        Instance = this;
    }

    public static HcmPlugIn Instance
    {
        get;
        private set;
    }

    protected override void ReadDocument(RhinoDoc doc, FileIO.BinaryArchiveReader archive, FileIO.FileReadOptions options)
    {
    }
    
    protected override bool ShouldCallWriteDocument(FileIO.FileWriteOptions options)
    {
        return true;
    }
    
    protected override void WriteDocument(RhinoDoc doc, FileIO.BinaryArchiveWriter archive, FileIO.FileWriteOptions options)
    {
    }

    protected override LoadReturnCode OnLoad(ref string errorMessage)
    {
        Type panelType = typeof(NewPanelHost);
        Panels.RegisterPanel(HcmPlugIn.Instance, panelType, "HcmToolsNew", Properties.Resources.FemTools32x32, PanelType.System);
        
        return base.OnLoad(ref errorMessage);
    }

    [System.Runtime.InteropServices.Guid("...")]
    public class NewPanelHost : RhinoWindows.Controls.WpfElementHost
    {
        public NewPanelHost(RhinoDoc docsn)
          : base(new NewPanel(docsn), null) // No view model (for this example)
        {
            InitializePanel();
        }

        void InitializePanel()
        {
            var panel_id = NewPanel.PanelId;
            var panel_visible = Panels.IsPanelVisible(panel_id);

            var type = typeof(NewPanel);
            if (panel_visible == false)
                Panels.OpenPanel(type.GUID);
        }

        public static System.Guid PanelId
        {
            get
            {
                return typeof(NewPanelHost).GUID;
            }
        }
    }
}

The command


    public class HcmCommandTools : Command
    {
        public HcmCommandTools()
        {
            Instance = this;
        }

        public static HcmCommandTools Instance
        {
            get;
            private set;
        }

        public override string EnglishName
        {
            get { return "HcmTools"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            var panel_id = typeof(NewPanelHost).GUID;

            if (mode == RunMode.Interactive)
            {
                Panels.OpenPanel(panel_id);
                return Result.Success;
            }

            var panel_visible = Panels.IsPanelVisible(panel_id);

            return Result.Success;
        }
    }

The Panel


    /// <summary>
    /// Interaction logic for NewPanel.xaml
    /// </summary>
    public partial class NewPanel
    {
        public bool IsEventsEnabled { get; private set; }

        public NewPanel(RhinoDoc documentSerialNumber)
        {
            //DataContext = new PaneViewModel(documentSerialNumber);
            InitializeComponent();

            IsEventsEnabled = false;
            //IsVisibleChanged += OnPanelVisibleChanged;
        }


        /// <summary>
        /// Returns the ID of this panel.
        /// </summary>
        public static System.Guid PanelId
        {
            get
            {
                return typeof(NewPanel).GUID;
            }
        }


        /// <summary>
        /// Handles IsVisible change events
        /// </summary>
        private void OnPanelVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            DebugWriteMethod();
            EnablePanelEvents((bool)e.NewValue);
        }

        /// <summary>
        /// Enables or disables panel event watchers
        /// </summary>
        private void EnablePanelEvents(bool bEnable)
        {
        }
...
    }

This line is thrown in an exception:

Panels.RegisterPanel(HcmPlugIn.Instance, panelType, "HcmToolsNew", Properties.Resources.FemTools32x32, PanelType.System);

I don’t know if Rhino has a strong dependency here, but which version of .NET are you using?

The Rhino Developer site says they support .NET Framework. That’s not the same as, for example, .NET 7 or .NET 8 which are the modern versions of .NET. .NET Framework is no longer developed, and when creating a new project in Visual Studio, is usually not the first WPF choice you see.

This may be a non-issue here, but throwing it out in case it is. When I last wrote a Rhino plugin, quite some time ago, it was in .NET Framework.

Edit, actually I see there’s .NET 7 for Rhino 8. The other page that mentions .NET Framework likely just needs updating.

Pete

Hi,

Actually I’m using .Net Framework 4.8 as this is quite an old project which I migrate from Win Forms to WPF and later to newer framework.

1 Like

Hi @karol.wierzbicki - I recently did a refactor of WPF panel inside Rhino and I used the WpfHost not the WpfElementHost like you are using. Maybe it helps?

What is the exception? Show the whole Exception/InnerException so we can see the callstack etc.

Hi,

Had the same problem here and found a solution : get your NewPanelHost class outside of your plugin class. For some reason if it’s declared here it cannot use the constructors properly …

Hope it helps,

Thomas