如何只在一个控件中设置ToolTip?

时间:2017-04-03 09:57:00

标签: c# wpf

我使用了带有行为的工具提示。因此,当单击控件时,将显示工具提示。

但是,当更改禁用控件时,不会出现此工具提示。 因为,鼠标事件未激活。因此,我使用了ContentContorl,它可以在更改禁用时激活鼠标事件。

但是,当我在一个网格中有几个控件时,我不知道如何激活唯一一个控件。

<Window.Resources>
    <Style TargetType="ContentControl" >
        <Setter Property="localToolTip:ToolTipTouchScreenBehavior.IsEnabled" Value="True"/>
    </Style>
    <Style TargetType="TextBlock" >
        <Setter Property="localToolTip:ToolTipTouchScreenBehavior.IsEnabled" Value="True"/>
    </Style>        
</Window.Resources>

<ContentControl ToolTip="This is ToolTip5 Test.">
            <Grid IsEnabled="False">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="300"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock  HorizontalAlignment="Left" Margin="5" TextWrapping="Wrap" Text="ToolTip Test5"  FontSize="25" 
                            ToolTipService.ShowOnDisabled="True" />
                <TextBox Grid.Column="1" Width="200" />

            </Grid>
</ContentControl>


public class ToolTipTouchScreenBehavior : Behavior<FrameworkElement>
{

    public static DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
            typeof(ToolTipTouchScreenBehavior), new FrameworkPropertyMetadata(false, OnIsEnabledChanged));

    public static bool GetIsEnabled(DependencyObject uie)
    {
        return (bool)uie.GetValue(IsEnabledProperty);
    }

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

    public static void OnIsEnabledChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e)
    {

        UIElement uie = dpo as UIElement;

        if (uie != null)
        {

            var behColl = Interaction.GetBehaviors(uie);

            var existingBehavior = behColl.FirstOrDefault(b => b.GetType() ==
                  typeof(ToolTipTouchScreenBehavior)) as ToolTipTouchScreenBehavior;

            if ((bool)e.NewValue == false && existingBehavior != null)
                behColl.Remove(existingBehavior);
            else if ((bool)e.NewValue == true && existingBehavior == null)
                behColl.Add(new ToolTipTouchScreenBehavior());

        }

    }

    Timer timer { get; set; }
    ToolTip toolTip { get; set; }

    protected override void OnAttached()
    {
        base.OnAttached();

        toolTip = new ToolTip();

        timer = new Timer();
        timer.Interval = 5000;
        timer.Elapsed += OnTimerElapsed;

        AssociatedObject.MouseLeave += OnMouseLeave;
        AssociatedObject.MouseLeftButtonUp += OnMouseLeftButtonUp;

    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        AssociatedObject.MouseLeave -= OnMouseLeave;
        AssociatedObject.MouseLeftButtonUp -= OnMouseLeftButtonUp;
    }

    public void OnMouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
    {
        CloseToolTip();
    }

    public void OnMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        try
        {



            //var temp = AssociatedObject.ToolTip;
            //if (((dynamic)sender).ToolTip != null)
            if (AssociatedObject.ToolTip != null)
            {
                if (AssociatedObject.ToolTip is string)
                    toolTip.Content = AssociatedObject.ToolTip;
                else
                    toolTip = (ToolTip)AssociatedObject.ToolTip;

                //Debug.WriteLine("ToolTip Opened: {0}, ToolTip Value: {1}", toolTip.IsOpen, toolTip.ToolTip);

                toolTip.IsOpen = true;
                timer.Start();

            }
        }
        catch (Exception ex)
        {
            throw ex;
        }



    }

    private void CloseToolTip()
    {

        if (timer.Enabled)
        {
            timer.Stop();
        }

        if (toolTip != null)
        {
            toolTip.IsOpen = false;
        }
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        Application.Current.Dispatcher.BeginInvoke((Action)CloseToolTip, DispatcherPriority.Send);
    }

}

当我有上面的代码时,我只想添加ToolTip只用于TextBlock。不是TextBox。

如何将ToolTip仅应用于一个特殊控件?

2 个答案:

答案 0 :(得分:0)

如果您的问题与 grek40 提到的问题相同,那么以下是答案:

如果您确实希望在禁用父控件时显示工具提示,则可以将ToolTipService.ShowOnDisabled属性设置为true。 WPF 2000things

答案 1 :(得分:0)

如果要对禁用的元素进行鼠标交互作出反应,可以向装饰图层添加视觉效果(对于已禁用的基础元素将保持启用状态)并在此处捕获输入。以下只是一个粗略的草图,其中一个Adorner仅在MouseLeftButtonUp对禁用的控件执行任意操作,并在附加属性上将adorner连接到某个框架元素(您可能希望利用您的行为)。

public class DisabledMouseUpAdorner : Adorner
{
    private Border _Child;
    private Action _OnDisabledMouseUp;

    public DisabledMouseUpAdorner(FrameworkElement element, Action onDisabledMouseUp)
        : base(element)
    {
        _OnDisabledMouseUp = onDisabledMouseUp;
        _Child = new Border();
        _Child.MouseLeftButtonUp += Adorner_Click;
        // actually you probably want an invisible adorner, but for demonstration lets add some color
        //_Child.Background = new SolidColorBrush(Colors.Transparent);
        _Child.Background = new SolidColorBrush(new Color() { A = 20, R = 255, G = 0, B = 0 });
        _Child.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
        _Child.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
        _Child.IsHitTestVisible = !element.IsEnabled;
        element.IsEnabledChanged += Adorned_IsEnabledChanged;
        AddVisualChild(_Child);
    }


    void Adorned_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        _Child.IsHitTestVisible = !AdornedElement.IsEnabled;
    }


    void Adorner_Click(object sender, RoutedEventArgs e)
    {
        if (_OnDisabledMouseUp != null)
        {
            _OnDisabledMouseUp();
        }
    }


    protected override int VisualChildrenCount
    { get { return 1; } }


    protected override Visual GetVisualChild(int index)
    {
        if (index != 0) throw new ArgumentOutOfRangeException();
        return _Child;
    }


    protected override Size MeasureOverride(Size constraint)
    {
        _Child.Measure(constraint);
        return base.MeasureOverride(constraint);
    }


    protected override Size ArrangeOverride(Size finalSize)
    {
        _Child.Arrange(new Rect(new Point(0, 0), finalSize));
        return finalSize;
    }
}



public static class Attached
{
    public static bool GetToolTipOnClickEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(ToolTipOnClickEnabledProperty);
    }

    public static void SetToolTipOnClickEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(ToolTipOnClickEnabledProperty, value);
    }

    // Using a DependencyProperty as the backing store for ToolTipOnClickEnabled.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ToolTipOnClickEnabledProperty =
        DependencyProperty.RegisterAttached("ToolTipOnClickEnabled", typeof(bool), typeof(Attached), new PropertyMetadata(false, new PropertyChangedCallback(OnToolTipOnClickChanged)));

    private static void OnToolTipOnClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as FrameworkElement;

        if (element != null)
        {
            if (element.IsLoaded)
            {
                if ((bool)e.NewValue == true)
                {
                    AddOverlay(element);
                }
                else
                {
                    RemoveOverlay(element);
                }
            }
            else
            {
                element.Loaded -= Element_Loaded;
                element.Loaded += Element_Loaded;
            }
        }
    }

    private static void Element_Loaded(object sender, RoutedEventArgs e)
    {
        var elem = sender as FrameworkElement;
        elem.Loaded -= Element_Loaded;
        if (GetToolTipOnClickEnabled(elem))
        {
            AddOverlay(elem);
        }
        else
        {
            RemoveOverlay(elem);
        }
    }

    private static void RemoveOverlay(FrameworkElement element)
    {
        var adl = AdornerLayer.GetAdornerLayer(element);
        var ad = adl.GetAdorners(element);
        foreach (var item in ad)
        {
            if (item is DisabledMouseUpAdorner) adl.Remove(item);
        }
    }

    private static void AddOverlay(FrameworkElement element)
    {
        var a = AdornerLayer.GetAdornerLayer(element);
        if (a != null)
        {
            a.Add(new DisabledMouseUpAdorner(element, () => ClickHandler(element)));
        }
        else
        {
        }
    }

    // whatever you actually want to do when the adorner triggers
    private static void ClickHandler(FrameworkElement element)
    {
        if (element.ToolTip == null)
        {
            return;
        }
        var tt = element.ToolTip as ToolTip ?? new ToolTip() { Content = element.ToolTip, StaysOpen = false };
        tt.IsOpen = true;
    }
}

用法

<TextBlock Text="ToolTip Test5"  FontSize="25"
    ToolTip="Shows on click when disabled"
    local:Attached.ToolTipOnClickEnabled="True" />