有没有办法遍历visual studioshell?

Is there a way to traverse through the visual studio shell?

有没有办法遍历所有 visual studio wpf 元素?我试图了解如何呈现选项卡以在 visual studio 扩展的上下文中添加额外的按钮 + 上下文菜单条目。

是的,我知道 Tab Studios 的存在。如果这不起作用,我不妨尝试一下是否满足我的需求。但在这一点上,我只是好奇如何做到这一点。

这是我到目前为止尝试过的方法:

internal class EditorMargin1 : StackPanel, IWpfTextViewMargin
    {
        /// <summary>
        /// Margin name.
        /// </summary>
        public const string MarginName = "EditorMargin1";

        /// <summary>
        /// A value indicating whether the object is disposed.
        /// </summary>
        private bool isDisposed;

        /// <summary>
        /// Initializes a new instance of the <see cref="EditorMargin1"/> class for a given <paramref name="textView"/>.
        /// </summary>
        /// <param name="textView">The <see cref="IWpfTextView"/> to attach the margin to.</param>
        public EditorMargin1(IWpfTextView textView)
        {
            this.ClipToBounds = true;

            var parents = GetParentsRecursive(textView);

            var start = 60;

            var white = new SolidColorBrush(Color.FromRgb((byte)255, (byte)255, (byte)255));
            white.Freeze();

            foreach (var parentElement in parents)
            {
                start += 20;
                var background = new SolidColorBrush(Color.FromRgb((byte)start, (byte)0, (byte)start));

                var changedColor = false;

                var colorableControl = parentElement as Control;
                if (colorableControl != null)
                {
                    colorableControl.Background = background;
                    changedColor = true;
                }

                this.Children.Add(new Label()
                {
                    Foreground = white,
                    Background = background,
                    Content = "Hello EditorMargin1 " + parentElement.GetType().FullName + " has changed color " + changedColor,
                });
            }
        }

        private IEnumerable<DependencyObject> GetParentsRecursive(IWpfTextView textView)
        {
            var control = textView as DependencyObject;
            while (control != null)
            {
                yield return control;
                control = LogicalTreeHelper.GetParent(control);
            }
        }

        #region IWpfTextViewMargin

        /// <summary>
        /// Gets the <see FrameworkElementlement"/> that implements the visual representation of the margin.
        /// </summary>
        /// <exception cref="ObjectDisposedException">The margin is disposed.</exception>
        public FrameworkElement VisualElement
        {
            // Since this margin implements Canvas, this is the object which renders
            // the margin.
            get
            {
                this.ThrowIfDisposed();
                return this;
            }
        }

        #endregion

        #region ITextViewMargin

        /// <summary>
        /// Gets the size of the margin.
        /// </summary>
        /// <remarks>
        /// For a horizontal margin this is the height of the margin,
        /// since the width will be determined by the <see cref="ITextView"/>.
        /// For a vertical margin this is the width of the margin,
        /// since the height will be determined by the <see cref="ITextView"/>.
        /// </remarks>
        /// <exception cref="ObjectDisposedException">The margin is disposed.</exception>
        public double MarginSize
        {
            get
            {
                this.ThrowIfDisposed();

                // Since this is a horizontal margin, its width will be bound to the width of the text view.
                // Therefore, its size is its height.
                return this.ActualHeight;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the margin is enabled.
        /// </summary>
        /// <exception cref="ObjectDisposedException">The margin is disposed.</exception>
        public bool Enabled
        {
            get
            {
                this.ThrowIfDisposed();

                // The margin should always be enabled
                return true;
            }
        }

        /// <summary>
        /// Gets the <see cref="ITextViewMargin"/> with the given <paramref name="marginName"/> or null if no match is found
        /// </summary>
        /// <param name="marginName">The name of the <see cref="ITextViewMargin"/></param>
        /// <returns>The <see cref="ITextViewMargin"/> named <paramref name="marginName"/>, or null if no match is found.</returns>
        /// <remarks>
        /// A margin returns itself if it is passed its own name. If the name does not match and it is a container margin, it
        /// forwards the call to its children. Margin name comparisons are case-insensitive.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="marginName"/> is null.</exception>
        public ITextViewMargin GetTextViewMargin(string marginName)
        {
            return string.Equals(marginName, EditorMargin1.MarginName, StringComparison.OrdinalIgnoreCase) ? this : null;
        }

        /// <summary>
        /// Disposes an instance of <see cref="EditorMargin1"/> class.
        /// </summary>
        public void Dispose()
        {
            if (!this.isDisposed)
            {
                GC.SuppressFinalize(this);
                this.isDisposed = true;
            }
        }

        #endregion

        /// <summary>
        /// Checks and throws <see cref="ObjectDisposedException"/> if the object is disposed.
        /// </summary>
        private void ThrowIfDisposed()
        {
            if (this.isDisposed)
            {
                throw new ObjectDisposedException(MarginName);
            }
        }
    }


    /// <summary>
    /// Export a <see cref="IWpfTextViewMarginProvider"/>, which returns an instance of the margin for the editor to use.
    /// </summary>
    [Export(typeof(IWpfTextViewMarginProvider))]
    [Name(EditorMargin1.MarginName)]
//  [Order(After = PredefinedMarginNames.HorizontalScrollBar)]  // Ensure that the margin occurs below the horizontal scrollbar
    [MarginContainer(PredefinedMarginNames.Top)]             // Set the container to the bottom of the editor window
    [ContentType("text")]                                       // Show this margin for all text-based types
    [TextViewRole(PredefinedTextViewRoles.Interactive)]
    internal sealed class EditorMargin1Factory : IWpfTextViewMarginProvider
    {
        #region IWpfTextViewMarginProvider

        /// <summary>
        /// Creates an <see cref="IWpfTextViewMargin"/> for the given <see cref="IWpfTextViewHost"/>.
        /// </summary>
        /// <param name="wpfTextViewHost">The <see cref="IWpfTextViewHost"/> for which to create the <see cref="IWpfTextViewMargin"/>.</param>
        /// <param name="marginContainer">The margin that will contain the newly-created margin.</param>
        /// <returns>The <see cref="IWpfTextViewMargin"/>.
        /// The value may be null if this <see cref="IWpfTextViewMarginProvider"/> does not participate for this context.
        /// </returns>
        public IWpfTextViewMargin CreateMargin(IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin marginContainer)
        {
            return new EditorMargin1(wpfTextViewHost.TextView);
        }

        #endregion
    }

我 运行 遇到的问题是,从遍历的角度来看,我无法通过 WpfTextViewHost。

有人知道以简单的方式遍历 window 的方法吗?

要遍历所有 Visual Studio wpf 元素,您可以从 System.Windows.Application.Current.MainWindow 开始并使用 System.Windows.Media.VisualTreeHelper.GetChild递归。请参阅以下示例代码 Hide title bar in Visual Studio 2013.