查找逻辑或Visual树弹出工具提示

问题描述:

说我有一个工具提示在XAML像这样指定的样式:

Say I have a ToolTip with a style specified in XAML like this:

<Button Content="Click me" ToolTip="Likes to be clicked">
    <Button.Resources>
        <Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="HasDropShadow" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToolTip}">
                        <StackPanel Background="Wheat" Height="200" Width="200">
                            <TextBlock x:Name="TxbTitle" FontSize="24" Text="ToolTip" Background="BurlyWood" />
                            <ContentPresenter />
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Resources>
</Button>



由于我在引用按钮并且该工具提示显示时,我怎么能找到工具提示弹出 / code>(后来找其视觉的孩子,如: TxbTitle )?

Given I have a reference to the Button and that the ToolTip is showing, how can I find the Popup of the ToolTip (and later look for its visual children, e.g. TxbTitle)?

更新

根据 pushpraj的回答我能够得到保持的(全)可视化树,它看起来是这样的:

Based on pushpraj's answer I was able to get a hold on the (full) visual tree, and it looks like this:

System.Windows.Controls.Primitives.PopupRoot
  System.Windows.Controls.Decorator
    System.Windows.Documents.NonLogicalAdornerDecorator
      System.Windows.Controls.ToolTip
        System.Windows.Controls.StackPanel
          System.Windows.Controls.TextBlock (TxbTitle)
          System.Windows.Controls.ContentPresenter
            System.Windows.Controls.TextBlock
      System.Windows.Documents.AdornerLayer

在这里我可以找到 TxbTitle 的TextBlock 。code>

(逻辑树是这样的:)

System.Windows.Controls.Primitives.Popup
  System.Windows.Controls.ToolTip
    System.String

pushpraj的回答却是基于我能获得工具提示实例举行。我已经得到的是按钮而已,而 Button.ToolTip 属性返回字符串喜欢被点击,而不是工具提示实例。

pushpraj's answer is however based on that I can get hold of the ToolTip instance. What I have got is the Button only, and Button.ToolTip property returns the string "Likes to be clicked", not the ToolTip instance.

所以更具体地说,问题是,我可以以某种方式获得的工具提示的的弹出搁置当我的一切是按钮

So more specifically, the question is, can I get hold of the ToolTip or the Popup in some way when all I've got is the Button.

(疯狂的想法:是有一些方法来枚举所有打开弹出 S')

(Crazy idea: is there some way to enumerate all open Popups?)

A 工具提示是一种弹出它承载工具提示内容

A ToolTip is a kind of Popup which hosts the tooltip content

和因为弹出窗口的在一个单独的窗口中承载所以它有它自己的逻辑和可视树

And since a Popup is hosted in a separate window so it have it's own logical and visual tree

下面您的信息是一个提示

for your information below are the Visual and Logical tree for a tooltip

视觉树

System.Windows.Controls.Primitives.PopupRoot
  System.Windows.Controls.Decorator
    System.Windows.Documents.NonLogicalAdornerDecorator
      System.Windows.Controls.ToolTip

逻辑树

System.Windows.Controls.Primitives.Popup
  System.Windows.Controls.ToolTip

请注意:因为弹出有它自己的根所以它可能无法从主窗口的视觉或逻辑树访问。

Note: since popup has it's own root so it may not be accessible from main window's visual or logical tree.

为了找到刀尖弹出

我已经使用附加属性找到一个提示

I have used attached properties to find the popup for a tooltip

namespace CSharpWPF
{

    public class ToolTipHelper : DependencyObject
    {
        public static bool GetIsEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEnabledProperty);
        }

        public static void SetIsEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(IsEnabledProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(ToolTipHelper), new PropertyMetadata(false,OnEnable));

        private static void OnEnable(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ToolTip t = d as ToolTip;

            DependencyObject parent = t;
            do
            {
                parent = VisualTreeHelper.GetParent(parent);
                if(parent!=null)
                    System.Diagnostics.Debug.Print(parent.GetType().FullName);
            } while (parent != null);

            parent = t;

            do
            {
                //first logical parent is the popup
                parent = LogicalTreeHelper.GetParent(parent);
                if (parent != null)
                    System.Diagnostics.Debug.Print(parent.GetType().FullName);
            } while (parent != null);

        }  
    }
}



XAML

xaml

<Button Content="Click me" ToolTip="Likes to be clicked">
    <Button.Resources>
        <Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}" 
               xmlns:l="clr-namespace:CSharpWPF">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="HasDropShadow" Value="True" />
            <Setter Property="l:ToolTipHelper.IsEnabled" Value="True"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToolTip}">
                        <StackPanel Background="Wheat" Height="200" Width="200">
                            <TextBlock x:Name="TxbTitle" FontSize="24" Text="ToolTip" Background="BurlyWood" />
                            <ContentPresenter />
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Resources>
</Button>



我已经加入新创建的附加属性为工具提示风格&LT; setter属性=L:ToolTipHelper.IsEnabledVALUE =真/&GT;

从后面

Retrieve ToolTip instance from code behind

在事件中,你不能指定样式或XAML的样式模板,那么后面的代码是你的检索工具提示实例

In event you can not specify the style or template of style from xaml then code behind is your way to retrieve the tooltip instance

示例代码

    Style style = new Style(typeof(ToolTip), (Style)this.FindResource(typeof(ToolTip)));
    style.Setters.Add(new Setter(ToolTipHelper.IsEnabledProperty, true));
    this.Resources.Add(typeof(ToolTip), style);



以上代码的工具提示创建一个样式对象,并增加了对 ToolTipHelper二传手。 IsEnabledProperty 并注入相同的样式窗口的资源

code above creates a style object for tooltip and adds a setter for ToolTipHelper.IsEnabledProperty and inject the same style to the resources of the window

作为导致属性更改处理程序 OnEnable 将在 ToolTipHelper 来显示当过需要的工具提示类调用。而在处理器的依赖对象将是实际情况提示您可能进一步操纵。

as result the property changed handler OnEnable will be invoked in the ToolTipHelper class when ever the tooltip is required to be displayed. and the dependency object in the handler will be the actual tooltip instance which you may further manipulate.