订阅事件

本演练介绍如何创建一个工具窗口,以响应正在运行的文档表(RDT)中的事件。 工具窗口承载实现 IVsRunningDocTableEvents的用户控件。 该方法 AdviseRunningDocTableEvents 将接口连接到事件。

订阅 RDT 事件

使用工具窗口创建扩展

  1. 使用 VSIX 模板创建名为 RDTExplorer 的项目,并添加名为 RDTExplorerWindow 的自定义工具窗口项模板。

    有关使用工具窗口创建扩展的详细信息,请参阅 “使用工具窗口创建扩展”。

订阅 RDT 事件

  1. 打开 RDTExplorerWindowControl.xaml 文件并删除名为 button1的按钮。 添加控件 ListBox 并接受默认名称。 Grid 元素应如下所示:

    <Grid>
        <StackPanel Orientation="Vertical" Margin="-10,10,10,0">
            <TextBlock Margin="10" HorizontalAlignment="Center">RDTExplorerWindow</TextBlock>
            <ListBox x:Name="listBox" Height="100" />
        </StackPanel>
    </Grid>
    
  2. 在代码视图中打开 RDTExplorerWindow.cs 文件。 将以下 using 指令添加到文件的开头。

    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell;
    using Microsoft.VisualStudio.Shell.Interop;
    
  3. RDTExplorerWindow修改类,以便除从ToolWindowPane类派生外,它还实现IVsRunningDocTableEvents接口。

    public class RDTExplorerWindow : ToolWindowPane, IVsRunningDocTableEvents
    {. . .}
    
  4. 实现 IVsRunningDocTableEvents

    • 实现 接口。 将光标置于 IVsRunningDocTableEvents 名称上。 应会在左边距看到灯泡。 单击灯泡右侧的向下箭头,然后选择“ 实现”接口
  5. 在接口中的每个方法中,将行 throw new NotImplementedException(); 替换为:

    return VSConstants.S_OK;
    
  6. 将 Cookie 字段添加到 RDTExplorerWindow 类。

    private uint rdtCookie;
    

    这会保存方法返回的 AdviseRunningDocTableEvents Cookie。

  7. 重写 RDTExplorerWindow 的 Initialize() 方法以注册 RDT 事件。 应始终在 ToolWindowPane 的 Initialize() 方法中获取服务,而不是在构造函数中获取。

    protected override void Initialize()
    {
        IVsRunningDocumentTable rdt = (IVsRunningDocumentTable)
        this.GetService(typeof(SVsRunningDocumentTable));
        rdt.AdviseRunningDocTableEvents(this, out rdtCookie);
    }
    

    SVsRunningDocumentTable调用该服务以获取IVsRunningDocumentTable接口。 此方法 AdviseRunningDocTableEvents 将 RDT 事件连接到实现 IVsRunningDocTableEvents的对象(在本例中为 RDTExplorer 对象)。

  8. 更新 RDTExplorerWindow 的 Dispose() 方法。

    protected override void Dispose(bool disposing)
    {
        // Release the RDT cookie.
        IVsRunningDocumentTable rdt = (IVsRunningDocumentTable)
            Package.GetGlobalService(typeof(SVsRunningDocumentTable));
        rdt.UnadviseRunningDocTableEvents(rdtCookie);
    
        base.Dispose(disposing);
    }
    

    该方法 UnadviseRunningDocTableEvents 删除与 RDT 事件通知之间的连接 RDTExplorer

  9. 在语句前面return,将以下行添加到处理程序的OnBeforeLastDocumentUnlock正文。

    public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
    {
        ((RDTExplorerWindowControl)this.Content).listBox.Items.Add("Entering OnBeforeLastDocumentUnlock");
        return VSConstants.S_OK;
    }
    
  10. 向处理程序正文 OnAfterFirstDocumentLock 和要在列表框中看到的其他事件添加类似的行。

    public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
    {
        ((RDTExplorerWindowControl)this.Content).listBox.Items.Add("Entering OnAfterFirstDocumentLock");
        return VSConstants.S_OK;
    }
    
  11. 生成项目并启动调试。 此时会显示 Visual Studio 实验实例。

  12. 打开 RDTExplorerWindow视图/其他 Windows/RDTExplorerWindow)。

    RDTExplorerWindow 窗口将打开,其中包含一个空事件列表。

  13. 打开或创建解决方案。

    触发 OnBeforeLastDocument 事件时 OnAfterFirstDocument ,每个事件的通知将显示在事件列表中。