Toggle visibility of form and region

Add-in Express™ Support Service
That's what is more important than anything else

Toggle visibility of form and region
 
James Telfer




Posts: 9
Joined: 2020-03-13
I have an ADXOlForm instance showing in the DockRight region of the screen.

What I would like to do is toggle this panel on and off with a toolbar button, and optionally allow closing with the form's close button. I've tried using various combinations of RegionState, the Visible property and the Activate(), Show() and Hide() methods with mixed success.

I can get the region/form to hide fully, but then it won't show again. Or, if I just set the RegionState to Hidden, the form is hidden but the Pane area remains visible and blank. Changing the RegionState back to Normal shows the form again though.

Below is the code I'm using. I drew on the post https://www.add-in-express.com/creating-addins-blog/2010/06/25/outlook-regions-forms-size-state/ as a guide, but I've tried to find other doco from guides and the class reference.


        private void adxButton_OnClick(object sender, IRibbonControl control, bool pressed)
        {
            var form  = rightPaneHost.GetCurrentForm();
            if (form != null)
            {
                switch (form.RegionState)
                {
                    case ADXRegionState.Normal:
                        form.Hide();
                        form.RegionState = ADXRegionState.Hidden;
                        break;

                    case ADXRegionState.Hidden:
                    case ADXRegionState.Minimized:
                    default:
                        form.RegionState = ADXRegionState.Normal;
                        form.Show();
                        break;
                }
            }
        }
Posted 08 Apr, 2020 08:57:24 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Hello James,

I've created a sample project; see http://temp.add-in-express.com/support/MyAddin37-JamesTelfer.zip. It toggles the visibility of the form. It preserves the form's hidden state whatever Outlook context your go to. It shows changing the caption of the Ribbon button to reflect the hidden state of the form.


Andrei Smolin
Add-in Express Team Leader
Posted 09 Apr, 2020 04:39:27 Top
James Telfer




Posts: 9
Joined: 2020-03-13
That's awesome Andrei, thanks. I don't think I would have got to that solution quickly if at all, so your solution was greatly appreciated.

My code now looks like the following. It shows the form if it's been minimized, as well as implementing your suggestions for how to toggle the visibility via a button. I'm not sure what the "Visible = false" does in the ADXOlForm to be honest, as it appears to work without that, but there's likely a case that I'm not testing.


// AddinModule.cs
        public bool Visible { get; set; } = true;

        private void adxButton_OnClick(object sender, IRibbonControl control, bool pressed)
        {
            var currentOutlookContext = control.Context;
            var form  = rightPaneHost.GetForm(currentOutlookContext);

            if (form == null)
            {
                return;
            }

            if (form.RegionState == ADXRegionState.Minimized)
            {
                // form is shown, just collapsed: restore it
                form.RegionState = ADXRegionState.Normal;
            }
            else
            {
                // toggle form shown state
                bool shouldShow = !Visible;

                if (shouldShow)
                {
                    form?.Show();
                }
                else
                {
                    form?.Hide();
                }

                Visible = shouldShow;
            }
        }

// ADXOlForm class:
        private void RightPaneContainer_ADXCloseButtonClick(object sender, ADXCloseButtonClickEventArgs e)
        {
            Namespace.AddinModule.CurrentInstance.Visible = !e.CloseForm;
        }

        private void RightPaneContainer_ADXAfterFormShow()
        {
            if (!Namespace.AddinModule.CurrentInstance.Visible)
            {
                Visible = false;
            }
        }
Posted 09 Apr, 2020 06:47:28 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Hello James,

I've looked in your code and found an issue in mine: whenever you get a Ribbon control's context, you should release it after use since the context object is a COM object. This doesn't apply to the context obtained through the arguments of the PropertyChanging event: that is, although the context object is still a COM object, you shouldn't release it in this case because Add-in Express manages that COM object.

Find the corrected code at the same location.


Andrei Smolin
Add-in Express Team Leader
Posted 09 Apr, 2020 06:59:54 Top
James Telfer




Posts: 9
Joined: 2020-03-13
Thanks Andrei!

Below is an update snippet I posted including the fix you've pointed out:


// AddinModule.cs 
public bool Visible { get; set; } = true; 

private void adxButton_OnClick(object sender, IRibbonControl control, bool pressed) 
{ 
    var currentOutlookContext = control.Context; 
    var form  = rightPaneHost.GetForm(currentOutlookContext); 

    try
    {
        if (form == null) 
        { 
            return; 
        } 

        if (form.RegionState == ADXRegionState.Minimized) 
        { 
            // form is shown, just collapsed: restore it 
            form.RegionState = ADXRegionState.Normal; 
        } 
        else 
        { 
            // toggle form shown state 
            bool shouldShow = !Visible; 

            if (shouldShow) 
            { 
                form?.Show(); 
            } 
            else 
            { 
                form?.Hide(); 
            } 

            Visible = shouldShow; 
        }
    }
    finally
    {
        Marshal.ReleaseComObject(currentOutlookContext);
    }
} 

// ADXOlForm class: 
private void RightPaneContainer_ADXCloseButtonClick(object sender, ADXCloseButtonClickEventArgs e) 
{ 
    Namespace.AddinModule.CurrentInstance.Visible = !e.CloseForm; 
} 

private void RightPaneContainer_ADXAfterFormShow() 
{ 
    if (!Namespace.AddinModule.CurrentInstance.Visible) 
    { 
        Visible = false; 
    } 
} 


Note that if you have a Disposable wrapper for COM objects, you can avoid a lot of try/finally:

var currentComObject = using new LeasedObject(control.Context);


(This uses the new using statements that are available in more recent versions of C#; a normal using would be required in earlier versions.

Where the class is:

public class LeasedObject<T> : IDisposable
{
    private disposed = false;
    private readonly T _leasedObject;

    public LeasedObject(T leasedObject)
    {
        _leasedObject = leasedObject;
    }

    public T Leased => _leasedObject;

    public void Dispose()
    {
        if (!disposed)
        {
            disposed = true;

            Marshal.ReleaseComObject(_leasedObject);
        }
    }
}
Posted 13 Apr, 2020 17:11:00 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Thank you, James!


Andrei Smolin
Add-in Express Team Leader
Posted 14 Apr, 2020 00:55:03 Top