【问题标题】:How to get active IWpfTextView in VS2019 extension (MEF)如何在 VS2019 扩展(MEF)中获得活动的 IWpfTextView
【发布时间】:2020-12-26 03:22:29
【问题描述】:

我正在尝试在 VS2019 扩展中获取活动的 C# 编辑器 IWpfTextView。我正在使用一个小型 MEF 服务将视图注入 VSAsyncPackage。但它不是很可靠 - 有时注入的视图是错误的(例如从另一个视图)或丢失。这是服务:

public interface IActiveViewAccessor
{
    IWpfTextView? ActiveView { get; }
}

[Export(typeof(IWpfTextViewConnectionListener))]
[Export(typeof(IActiveViewAccessor))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class ActiveViewConnectionListener : IWpfTextViewConnectionListener, IActiveViewAccessor
    {
    public IWpfTextView? ActiveView { get; private set; }

    public void SubjectBuffersConnected(IWpfTextView textView, ConnectionReason reason, Collection<ITextBuffer> subjectBuffers)
    {
        this.ActiveView = textView;
    }

    public void SubjectBuffersDisconnected(IWpfTextView textView, ConnectionReason reason, Collection<ITextBuffer> subjectBuffers)
    {
        this.ActiveView = null;
    }
}

这个服务被注入到 VSPackage 中:

this.viewAccessor = this.exportProvider.GetExportedValue<IActiveViewAccessor>();

它被用作:

var view = this.viewAccessor?.ActiveView;

有没有更好更稳定的方式在异步VSPackage中获取IWpfTextView?

到目前为止,这里有一些相关的问题,但并不完全符合我的预期:

  1. How to get IWpfTextView from command Visual Studio Extension 2017 (2017)
  2. How can I get IWpfTextView for EnvDte.ActiveDocument? (2013)
  3. Access current code pane in Visual Studio Extension (2012)

【问题讨论】:

  • 我建议您可以添加有关您的提示的答案,而不是在问题中。
  • @PerryQian-MSFT 我不完全确定访问活动 IWpfTextView 的“现代”或“正确”方式,但您的建议是有道理的,谢谢。完成。

标签: c# visual-studio-2019 mef visual-studio-extensions


【解决方案1】:

经过一番调试和探索,我得出结论,我最初的做法非常幼稚。因为IWpfTextViewConnectionListener 在简单情况下每个编辑器窗口只触发一次,并且在已连接的视图之间切换时不会触发。

在试用它并潜入VsVim > VsAdapter.cs 之后,我将IActiveViewAccessor 更改为:

public interface IActiveViewAccessor
{
    IWpfTextView? ActiveView { get; }
}

[Export(typeof(IActiveViewAccessor))]
internal sealed class ActiveViewAccessor : IActiveViewAccessor
{
    private readonly SVsServiceProvider serviceProvider;
    private readonly IVsEditorAdaptersFactoryService editorAdaptersFactoryService;

    [ImportingConstructor]
    public ActiveViewAccessor(
        SVsServiceProvider vsServiceProvider,
        IVsEditorAdaptersFactoryService editorAdaptersFactoryService)
    {
        this.serviceProvider = vsServiceProvider;
        this.editorAdaptersFactoryService = editorAdaptersFactoryService;
    }

    public IWpfTextView? ActiveView
    {
        get
        {
            IVsTextManager2 textManager =
                serviceProvider.GetService<SVsTextManager, IVsTextManager2>();

            if (textManager == null)
            {
                return null;
            }

            int hr = textManager.GetActiveView2(
                fMustHaveFocus: 1,
                pBuffer: null,
                grfIncludeViewFrameType: (uint)_VIEWFRAMETYPE.vftCodeWindow,
                ppView: out IVsTextView vsTextView);

            if (ErrorHandler.Failed(hr))
            {
                return null;
            }

            return editorAdaptersFactoryService.GetWpfTextView(vsTextView);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    相关资源
    最近更新 更多