Я разрабатываю расширение Visual Studio, в котором одна из реализованных команд должна быть доступна только тогда, когда активный документ является текстовым документом (например, «Toggle Bookmark» Visual Studio). Проблема в том, что я не могу понять, как сказать, когда это так.
Сейчас у меня есть полурабочее решение. В методе Initialize
пакета я подписываюсь на событие WindowActivated
DTE, а затем всякий раз, когда активируется окно, я проверяю, имеет ли свойство окна DocumentData
тип TextDocument
:
protected override void Initialize()
{
base.Initialize();
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
dte.Events.WindowEvents.WindowActivated += WindowEventsOnWindowActivated;
//More initialization here...
}
//This is checked from command's BeforeQueryStatus
public bool ActiveDocumentIsText { get; private set; } = false;
private void WindowEventsOnWindowActivated(Window gotFocus, Window lostFocus)
{
if (gotFocus.Kind != "Document")
return; //It's not a document (e.g. it's a tool window)
TextDocument textDoc = gotFocus.DocumentData as TextDocument;
ActiveDocumentIsText = textDoc != null;
}
Проблема с этим подходом заключается в том, что 1) Window.DocumentData задокументирован как «только для внутреннего использования .NET Framework», и 2) это дает ложное срабатывание, когда документ, который имеет как представление кода, так и представление дизайна (например, файл .visxmanifest
) открыт в режиме конструктора.
Я пытался использовать IVsTextManager.GetActiveView, но это возвращает последнее открытое активное текстовое представление, поэтому, если я открою файл .txt, а затем файл .png, он вернет данные для файла .txt, даже если это больше не активный документ.
Итак, как мне проверить, является ли активный документ текстовым документом или представлением кода документа, у которого может быть дизайнер... и, если возможно, не использовать "недокументированные" классы/члены?
ОБНОВЛЕНИЕ: я нашел немного лучшее решение. Внутри обработчика активации окна:
ActiveDocumentIsText = gotFocus.Document.Object("TextDocument") != null;
По крайней мере, это правильно задокументировано, но я до сих пор есть проблема ложных срабатываний с дизайнерами.