无法将事件附加到自定义任务窗格。 VSTO,Excel 2016

Trouble attaching an event to a custom task pane. VSTO, Excel 2016

背景

我目前正在开发 VSTO2015 和 Excel 2016 中的应用程序。该应用程序在不同的 windows 中管理多个 CustomTaskPanes。我试图让 // some code 在任务窗格打开或关闭时触发。为了处理各种windows,我实现了一个与此非常相似的结构;

CustomTaskPane in Excel doesn't appear in new Workbooks

ThisAddIn.cs 包含以下 class;

public class TaskPaneManager
    {
        static Dictionary<string, Microsoft.Office.Tools.CustomTaskPane> _createdPanes = new Dictionary<string, Microsoft.Office.Tools.CustomTaskPane>();

        /// <summary>
        /// Gets the taskpane by name (if exists for current excel window then returns existing instance, otherwise uses taskPaneCreatorFunc to create one). 
        /// </summary>
        /// <param name="taskPaneId">Some string to identify the taskpane</param>
        /// <param name="taskPaneTitle">Display title of the taskpane</param>
        /// <param name="taskPaneCreatorFunc">The function that will construct the taskpane if one does not already exist in the current Excel window.</param>
        public static Microsoft.Office.Tools.CustomTaskPane GetTaskPane(string taskPaneId, string taskPaneTitle, Func<UserControl> taskPaneCreatorFunc)
        {
            string key = string.Format("{0}({1})", taskPaneId, Globals.ThisAddIn.Application.Hwnd);
            string title = taskPaneId;
            string windowId = Globals.ThisAddIn.Application.Hwnd.ToString();

            if (!_createdPanes.ContainsKey(key))
            {
                var customTaskPane = taskPaneCreatorFunc();
                var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
                _createdPanes[key] = pane;

                //
                // Set the task pane width as set in the App.Config
                //
                pane.Width = Convert.ToInt32(ConfigurationManager.AppSettings["TaskPaneWidth"]);
            }
            return _createdPanes[key];
        }
    ....

我的电话来自 Ribbon.cs

private void btnUploadWizard_Click(object sender, RibbonControlEventArgs e)
{
    // Check for configuration sheet first.

    string title = "Upload Wizard";

    TaskPaneManager.isConfigurationCreated();

    var UploadWizardTaskpane = TaskPaneManager.GetTaskPane(title, title, () => new TaskPaneUploadWizard());
    UploadWizardTaskpane.Visible = !UploadWizardTaskpane.Visible;

}

问题:事件处理程序

我很难触发事件处理程序。我不知道我做错了什么。在 TaskPaneDesigner 中,我使用 this.VisibleChanged += new System.EventHandler(this.TaskPaneUploadWizard_VisibleChanged); 附加事件,然后在我的 TaskPaneUploadWizard class 中定义它,如下所示;

public partial class TaskPaneUploadWizard : UserControl
{
    ...

    public TaskPaneUploadWizard()
    {
        InitializeComponent();
    }

    private void TaskPaneUploadWizard_VisibleChanged(object sender, EventArgs e)
    {
        // Some code
    }

我的想法

在我看来,我要么将 eventHandler 附加到 CustomTaskPane 对象以外的对象,要么在创建 CustomTaskPane 之前附加它。

求助!

要检测任务窗格是打开还是关闭,您必须附加到 paneVisibleChanged 事件。

所以最简单的解决方案是在 GetTaskPane 方法中只添加一行代码:

var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
// This is the new line to be added.
pane.VisibleChanged += (s, e) => customTaskPane.Visible = pane.Visible;
_createdPanes[key] = pane;

现在整个任务窗格的可见性将传递给它的内容,// some code应该被执行。

或者,如果您出于某种原因不想手动设置 customTaskPane.Visible,您也可以直接在这个新的事件处理程序中执行您的代码:

pane.VisibleChanged += (s, e) => { /* some code */ };

但我个人更愿意推荐第一种方法,因为它似乎更适合您现有的代码。

var UploadWizardTaskpane = TaskPaneManager.GetTaskPane(title, title, () => new TaskPaneUploadWizard());

这是在创建一个 CustomTaskPane 而不是 TaskPaneUploadWizard 对象

好像this.VisibleChanged += new System.EventHandler(this.TaskPaneUploadWizard_VisibleChanged);作用于TaskPaneUploadWizard,而TaskPaneUploadWizard只是CustomTaskPane

的客人

请注意 CustomTaskPane 的可见性不影响 TaskPaneUploadWizard

我的建议

您从设计器中删除 VisibleChanged,您将在您的 TaskPaneUploadWizard

中手动添加它
public partial class TaskPaneUploadWizard : UserControl
{
    //{---}
    CustomTaskPane _HostPane;
    public CustomTaskPane HostPane
    {
         get => _HostPane;
         set
         {
             if(_HostPane == value)
                 return;
             _HostPane?.VisibleChanged -= TaskPaneUploadWizard_VisibleChanged;
             _HostPane = value;
             _HostPane?.VisibleChanged += TaskPaneUploadWizard_VisibleChanged;
         }
    }
    //{---}
    private void TaskPaneUploadWizard_VisibleChanged(object sender, EventArgs e)
    {
        // Some code
    }
    //{---}

然后在GetTaskPane你说

//{---}
var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
(customTaskPane as TaskPaneUploadWizard).HostPane = pane;
//{---}