如何在 VS2019 扩展 (MEF) 中获得活动的 IWpfTextView [英] How to get active IWpfTextView in VS2019 extension (MEF)
问题描述
我正在尝试在 VS2019 扩展中获取活动的 C# 编辑器 IWpfTextView.我正在使用小型 MEF 服务将视图注入 VSAsyncPackage.但它不是很可靠 - 有时注入的视图是错误的(例如从另一个视图)或丢失.这是服务:
I'm trying to get the active C# Editor IWpfTextView in VS2019 extension. I'm using a small MEF service to inject a view into the VSAsyncPackage. But it is not very reliable - sometimes the injected view is wrong (e.g. from another view) or missing. Here is the service:
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 service is being injected into the VSPackage as:
this.viewAccessor = this.exportProvider.GetExportedValue<IActiveViewAccessor>();
它被用作:
var view = this.viewAccessor?.ActiveView;
是否有更好更稳定的方式在异步 VSPackage 中获取 IWpfTextView?
Is there a better and more stable way to get IWpfTextView in the async VSPackage?
到目前为止,这里有一些相关的问题,但并不完全符合我的预期:
So far, here are some related questions but not exactly what I'd expected:
- 如何从命令 Visual Studio 扩展中获取 IWpfTextView2017 (2017)
- 如何获取 EnvDte.ActiveDocument 的 IWpfTextView?(2013)
- 在 Visual Studio 扩展 (2012) 中访问当前代码窗格一个>
推荐答案
经过一些调试和探索,我得出结论,我最初的方法非常幼稚.因为 IWpfTextViewConnectionListener
在一个简单的情况下每个编辑器窗口只触发一次,并且在已经连接的视图之间切换时不会触发.
After a bit of debugging and exploring, I concluded that my initial approach is very naive. Because IWpfTextViewConnectionListener
is only firing once per editor window in a simple case, and it's not firing during switching between already connected views.
在试用它并潜入 我已将 IActiveViewAccessor
更改为:
After experimenting with it and sneaking into VsVim > VsAdapter.cs I've changed IActiveViewAccessor
to the this:
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);
}
}
}
这篇关于如何在 VS2019 扩展 (MEF) 中获得活动的 IWpfTextView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!