C# 在逻辑树或可视树中查找工具提示弹出窗口

C# 在逻辑树或可视树中查找工具提示弹出窗口,c#,wpf,C#,Wpf,假设我有一个在XAML中指定样式的工具提示,如下所示: <Button Content="Click me" ToolTip="Likes to be clicked"> <Button.Resources> <Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}"> <Setter Property="

假设我有一个在XAML中指定样式的
工具提示,如下所示:

<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>
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
System.Windows.Controls.Primitives.Popup
  System.Windows.Controls.ToolTip
    System.String
在这里我可以找到
txbttitle
TextBlock

(逻辑树如下所示:)

然而,pushpraj的回答是基于我可以获得
工具提示
实例。我得到的只是
按钮和
按钮。ToolTip
属性返回字符串
“喜欢被单击”
,而不是
ToolTip
实例

因此,更具体地说,问题是,当我只有
按钮时,我是否可以以某种方式获得
工具提示
弹出窗口


(疯狂的想法:有没有办法枚举所有打开的
弹出窗口
s?

工具提示
是一种托管工具提示内容的
弹出窗口

由于弹出窗口位于单独的窗口中,因此它有自己的逻辑和可视树

下面是工具提示的视觉和逻辑树,供您参考

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);

        }  
    }
}
可视化树

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
逻辑树

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
注意:由于弹出窗口有自己的根,所以可能无法从主窗口的视觉或逻辑树访问它

查找工具提示弹出窗口

我使用附加属性查找工具提示的弹出窗口

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

上面的代码为tooltip创建了一个样式对象,并为
ToolTiHelper.IsEnabledProperty添加了一个setter,并将相同的样式注入到窗口的资源中


因此,当需要显示工具提示时,将在
ToolTipHelper
类中调用属性已更改的处理程序
OnEnable
。处理程序中的依赖项对象将是您可以进一步操作的实际工具提示实例。

您希望在什么事件中访问它?它不是事件。我正在开发一个“工具”,在这里我需要信息,它从另一个线程访问元素。但我也对纯粹的理解感兴趣…很好的答案(+1),它有助于我的理解。我已经根据你的答案更新了我的问题。然而,您的代码假设我可以访问XAML,不幸的是,我没有那个luxary。。。请参阅我对问题的更新。如果您可以通过代码隐藏访问按钮或任何父元素,那么您可以做的是使用setter for
l:ToolTipper.IsEnabled
将工具提示的样式插入根元素的资源中,并在每次打开工具提示时将其弹出。我在答案中添加了示例代码。很好的解决方案!谢谢