2017-04-03 58 views
0

我已经使用ToolTip with Behavior。所以,当点击控件时,将出现工具提示。如何只在一个控件中设置工具提示?

但是,当更改控件的禁用时,此工具提示未出现。 因为鼠标事件未被激活。所以,我使用了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); 
    } 

} 

当我有上面的代码,我只是想添加工具提示仅用于TextBlock。不是TextBox。

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

+0

如果我理解正确的话,你应该问如何对鼠标事件作出反应上禁用的控制,以激活工具提示? – grek40

回答

0

如果您想对禁用的元素的鼠标交互做出反应,可以向adorner图层添加一个可见(它将保持为禁用的基础元素启用)并捕获输入。下面只是一个粗略的草图,Adorner仅对MouseLeftButtonUp执行任意操作,仅对禁用的控件和附加属性将装饰器连接到某个框架元素(您可能需要改用您的行为)。

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" /> 
+0

哇,它工作,对我很有帮助。 非常感谢。 – Song

+0

@宋如果这是有帮助的,你应该把它标记为答案;) – grek40

0

如果由grek40提到你的问题是相同的,则以下是答案:

如果你希望在父控件被禁用要显示的工具提示,您可以设置ToolTipService.ShowOnDisabled属性为真。 WPF 2000things

+0

我认为问题在于不仅在鼠标悬停时自动显示工具提示,而且还要处理特殊输入设备(触摸板),鼠标不会神奇地停留在某种控制之下。对于大多数正常使用情况来说,还是要提到这个属性。 – grek40

相关问题