Problem with WinForms controls in Add-ins

Sep 24, 2008 at 6:15 PM

I am having trouble with hosting WinForms controls in add-ins.  I use the FrameworkElementAdapters to tunnel them through the pipeline, and I am running the add-in in the same app-domain as the host app.  The pipeline is included below.  If I create an add-in that implements IWorkspaceComponentFactory and returns an IWorkspaceComponent that is a WinForms panel that contains a button, and I put that IWorkspaceComponent on a form, it has problems.  If I set the background on the panel to transparent, it shows up as white in the host app.  If I call BaseControl on the IWorkspaceComponent then put that on the form, it works.  (Of course, this will break if I ever try to run the add-in in a separate app domain, but one problem at a time).  Of course, then the control on the form is no longer an IWorkspaceComponent, and I can't access properties defined on that interface.

I pretty much lifted this code from examples of using WinForms controls with add-ins - I've checked a few things and think I have everything right.  Has anyone else done anything like this?  Any suggestions would be appreciated.  Sorry about the volume of code following...

I have a contract like the following:

    public interface IWorkspaceComponent : IContract, IAddInControl
    {
        INativeHandleContract   GetControl();
        object BaseControl        { get; }
        bool   ReadOnly            { get; set; }
    }   //  IWorkspaceComponent

    [AddInContract]
    public interface IWorkspaceComponentFactory : IFactoryBase
    {
        bool Initialize(IGlobalContext context);
        IWorkspaceComponent CreateControl(bool inDesignMode, IRecordContext context);
    }

The add-in views are

    public interface IWorkspaceComponent
    {
        System.Windows.Forms.Control GetControl();
        bool ReadOnly           { get; set; }
    }   //  IWorkspaceComponent

    /// <summary>
    /// Interface that must be implemented by any add-in that will be used to
    /// create IWorkspaceComponent add-ins.
    /// </summary>
    [AddInBase()]
    public interface IWorkspaceComponentFactory : IFactoryBase
    {
        bool Initialize(IGlobalContext context);
        IWorkspaceComponent CreateControl(bool inDesignMode, IRecordContext context);
    }

Host views are the same, without the [AddInBase()] attribute on the factory.

Host Side adapters:

    public class WorkspaceComponentHostSideAdapter : ElementHost, RightNow.AddIns.HostViews.IWorkspaceComponent
    {
        private RightNow.AddIns.Contracts.IWorkspaceComponent contract;
        private ContractHandle handle;

        public WorkspaceComponentHostSideAdapter(RightNow.AddIns.Contracts.IWorkspaceComponent newContract)
        {
            contract = newContract;
            Child = FrameworkElementAdapters.ContractToViewAdapter(contract.GetControl());
            handle = new ContractHandle(newContract);
        }

        public bool ReadOnly
        {
            get { return contract.ReadOnly; }
            set { contract.ReadOnly = value; }
        }

        public object BaseControl
        {
            get { return contract.BaseControl; }
        }

        //  IDisposable Members
    }   //  WorkspaceComponentHostSideAdapter


    [HostAdapter()]
    public class WorkspaceComponentFactoryHostSideAdapter : RightNow.AddIns.HostViews.IWorkspaceComponentFactory, IDisposable
    {
        private RightNow.AddIns.Contracts.IWorkspaceComponentFactory contract;
        private ContractHandle handle;

        public WorkspaceComponentFactoryHostSideAdapter(RightNow.AddIns.Contracts.IWorkspaceComponentFactory newContract)
        {
            contract = newContract;
            handle = new ContractHandle(contract);
        }

        public bool Initialize(RightNow.AddIns.HostViews.IGlobalContext context)
        {
            return contract.Initialize(new GlobalContextHostSideAdapter(context));
        }

        public RightNow.AddIns.HostViews.IWorkspaceComponent CreateControl(bool inDesignMode, RightNow.AddIns.HostViews.IRecordContext context)
        {
            return new WorkspaceComponentHostSideAdapter(contract.CreateControl(inDesignMode, new RecordContextHostSideAdapter(context)));
        }

        //  IDisposable members
    }   //  WorkspaceComponentHostSideAdapter



Add-in side adapters:
    public class WorkspaceComponentAddInSideAdapter : ContractBase, RightNow.AddIns.Contracts.IWorkspaceComponent
    {
        private readonly RightNow.AddIns.AddInViews.IWorkspaceComponent view;

        public WorkspaceComponentAddInSideAdapter(RightNow.AddIns.AddInViews.IWorkspaceComponent newView)
        {
            view = newView;
        }

        public INativeHandleContract GetControl()
        {
            WindowsFormsHost host = new WindowsFormsHost();
            host.Child = view.GetControl();
            return FrameworkElementAdapters.ViewToContractAdapter(host);
        }

        public object BaseControl
        {
            get { return view.GetControl(); }
        }

        public bool         ReadOnly
        {
            get { return view.ReadOnly;  }
            set { view.ReadOnly = value; }
        }

    }   //  WorkspaceComponentAddInSideAdapter


    [AddInAdapter()]
    public class WorkspaceComponentFactoryAddInSideAdapter : ContractBase, RightNow.AddIns.Contracts.IWorkspaceComponentFactory
    {
        private RightNow.AddIns.AddInViews.IWorkspaceComponentFactory view;

        public WorkspaceComponentFactoryAddInSideAdapter(RightNow.AddIns.AddInViews.IWorkspaceComponentFactory newView)
        {
            view = newView;
        }

        public bool Initialize(RightNow.AddIns.Contracts.IGlobalContext context)
        {
            return view.Initialize(new GlobalContextAddInSideAdapter(context));
        }

        public RightNow.AddIns.Contracts.IWorkspaceComponent CreateControl(bool inDesignMode, RightNow.AddIns.Contracts.IRecordContext context)
        {
            return new WorkspaceComponentAddInSideAdapter(view.CreateControl(inDesignMode, new RecordContextAddInSideAdapter(context)));
        }
    }   //  WorkspaceComponentFactoryAddInSideAdapter