void checkSubscribe(IVsWindowFrame vsWindowFrame)
        {
            if (_vsWindowFrameSet.Contains(vsWindowFrame))
            {
                return;
            }

            // Even though project files are in the running document table events about their dirty state are not always
            // properly raised by Visual Studio.  In particular when they are modified via the project property
            // designer (aka application designer).  However these IVsWindowFrame implementations do implement the
            // INotifyPropertyChanged interface and we can hook into the IsDocumentDirty property instead
            //
            // This is an implementation detail of IVsWindowFrame (specifically WindowFrame inside the DLL
            // Microsoft.VisualStudio.Platform.WindowManagement).  Hence it can change from version to version of
            // Visual Studio.  But this is the behavior in 2010+ and unlikely to change.  Need to be aware of these
            // potential break though going forward
            var notifyPropertyChanged = vsWindowFrame as INotifyPropertyChanged;
            var vsWindowFrame2        = vsWindowFrame as IVsWindowFrame2;

            if (notifyPropertyChanged == null || vsWindowFrame2 == null)
            {
                return;
            }

            var disp = Observable.FromEventPattern <PropertyChangedEventHandler, PropertyChangedEventArgs>(x => notifyPropertyChanged.PropertyChanged += x, x => notifyPropertyChanged.PropertyChanged -= x)
                       .Where(x => x.EventArgs.PropertyName == "DocumentIsDirty")
                       .Select(_ => Unit.Default)
                       .Multicast(_changed)
                       .Connect();

            var vsWindowFrameMonitor = new VsWindowFrameMonitor(this, vsWindowFrame, disp);

            if (!ErrorHandler.Succeeded(vsWindowFrame2.Advise(vsWindowFrameMonitor, out vsWindowFrameMonitor.Cookie)))
            {
                return;
            }

            _vsWindowFrameSet.Add(vsWindowFrame);
        }
        void checkSubscribe(IVsWindowFrame vsWindowFrame)
        {
            if (_vsWindowFrameSet.Contains(vsWindowFrame)) {
                return;
            }

            // Even though project files are in the running document table events about their dirty state are not always
            // properly raised by Visual Studio.  In particular when they are modified via the project property
            // designer (aka application designer).  However these IVsWindowFrame implementations do implement the
            // INotifyPropertyChanged interface and we can hook into the IsDocumentDirty property instead
            //
            // This is an implementation detail of IVsWindowFrame (specifically WindowFrame inside the DLL
            // Microsoft.VisualStudio.Platform.WindowManagement).  Hence it can change from version to version of
            // Visual Studio.  But this is the behavior in 2010+ and unlikely to change.  Need to be aware of these
            // potential break though going forward
            var notifyPropertyChanged = vsWindowFrame as INotifyPropertyChanged;
            var vsWindowFrame2 = vsWindowFrame as IVsWindowFrame2;

            if (notifyPropertyChanged == null || vsWindowFrame2 == null) {
                return;
            }

            var disp = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(x => notifyPropertyChanged.PropertyChanged += x, x => notifyPropertyChanged.PropertyChanged -= x)
                .Where(x => x.EventArgs.PropertyName == "DocumentIsDirty")
                .Select(_ => Unit.Default)
                .Multicast(_changed)
                .Connect();

            var vsWindowFrameMonitor = new VsWindowFrameMonitor(this, vsWindowFrame, disp);
            if (!ErrorHandler.Succeeded(vsWindowFrame2.Advise(vsWindowFrameMonitor, out vsWindowFrameMonitor.Cookie))) {
                return;
            }

            _vsWindowFrameSet.Add(vsWindowFrame);
        }