我正在制作一个具有内联差异视图功能的 Visual Studio IDE 扩展。
CreateDifferenceView
创建了一个FrameWorkElement
,要注意这个方法会创建两个内部的IWpfTextView
。然后我使用 AddAdornment
将其附加到 IWpfTextView
。
问题是装饰无法正确接收键盘焦点。最初,我可以输入它,但是像 CTRL+A、CTRL+C 等命令...不起作用,它们将由主机
IWpfTextView
接收/处理,而不是由主机接收/处理。装饰品。
从这个博客学习,我已经通过使用
AddCommandFilter
成功地实现了该工作,并将命令转发到由IVsTextView
创建的内部CreateDifferenceView
。
现在键盘命令可以正常工作,但仍然存在一个问题,装饰仍然没有获得正确的焦点。您可以看到,虽然我可以选择装饰中的文本,但选择仍然显示为“失焦”灰色,并且即使我单击主机
IWpfTextView
也不会失去其选择焦点。装饰品。抱歉,我必须附上 GIF,但没有更好的方法来描述问题。:
我尝试过的:
FocusManager.SetIsFocusScope
设置范围。UIElement.Focus
和内部 IWpfDifferenceViewer.VisualElement
上呼唤 IWpfTextView.VisualElement
SendExplicitFocus
IVsTextView
MRE(
MefProvider
仅导入这些组件):
var docview = await VS.Documents.GetActiveDocumentViewAsync();
var contentType = docview.TextBuffer.ContentType;
var leftBuffer = MefProvider.TextBufferFactoryService.CreateTextBuffer("left content", contentType);
var rightBuffer = MefProvider.TextBufferFactoryService.CreateTextBuffer("right content", contentType);
var diffBuffer = MefProvider.DifferenceBufferFactory.CreateDifferenceBuffer(leftBuffer, rightBuffer);
var diffViewer = MefProvider.DifferenceViewerFactory.CreateDifferenceView(diffBuffer);
var adornmentLayer = docview.TextView.GetAdornmentLayer("MyAdornmentLayer");
adornmentLayer.AddAdornment(AdornmentPositioningBehavior.OwnerControlled, null, null, diffViewer.VisualElement, null);
解决方法是使用
Microsoft.VisualStudio.Platform.VSEditor.dll
中未记录的内部函数:
diffViewer.VisualElement.GotFocus += (o, e) => {
AggregateFocusInterceptor.SetInterceptsAggregateFocus(hostView as DependencyObject, true);
};
diffViewer.VisualElement.LostFocus += (o, e) => {
AggregateFocusInterceptor.SetInterceptsAggregateFocus(hostView as DependencyObject, false);
};
ISpaceReservationManager
然后向其添加代理并触发其 GotFocus
事件来获得部分成功的结果。从技术上讲,这应该可行,但是,在装饰文本视图获得焦点后,主视图就会夺回焦点。我怀疑这可能与触发事件的顺序有关。
不接受这作为答案,因为这只是一种解决方法,应该有更正确的方法来做到这一点。