TextBlockAttach.cs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Media;
  5. using HandyControl.Data;
  6. using HandyControl.Tools.Helper;
  7. namespace HandyControl.Controls;
  8. public class TextBlockAttach
  9. {
  10. public static readonly DependencyProperty AutoTooltipProperty = DependencyProperty.RegisterAttached(
  11. "AutoTooltip", typeof(bool), typeof(TextBlockAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnAutoTooltipChanged));
  12. private static void OnAutoTooltipChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  13. {
  14. if (d is TextBlock ctl)
  15. {
  16. if ((bool) e.NewValue)
  17. {
  18. UpdateTooltip(ctl);
  19. ctl.SizeChanged += TextBlock_SizeChanged;
  20. }
  21. else
  22. {
  23. ctl.SizeChanged -= TextBlock_SizeChanged;
  24. }
  25. }
  26. }
  27. public static void SetAutoTooltip(DependencyObject element, bool value)
  28. => element.SetValue(AutoTooltipProperty, ValueBoxes.BooleanBox(value));
  29. public static bool GetAutoTooltip(DependencyObject element)
  30. => (bool) element.GetValue(AutoTooltipProperty);
  31. private static void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
  32. {
  33. if (sender is TextBlock textBlock)
  34. {
  35. UpdateTooltip(textBlock);
  36. }
  37. }
  38. private static void UpdateTooltip(TextBlock textBlock)
  39. {
  40. textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
  41. var width = textBlock.DesiredSize.Width - textBlock.Margin.Left - textBlock.Margin.Right;
  42. // the code Math.Abs(CalcTextWidth(textBlock) - width) > 1 is not elegant end even bugly,
  43. // while it does solve the problem of Tooltip failure in some cases
  44. if (textBlock.RenderSize.Width > width || textBlock.ActualWidth < width || Math.Abs(CalcTextWidth(textBlock) - width) > 1)
  45. {
  46. ToolTipService.SetToolTip(textBlock, textBlock.Text);
  47. }
  48. else
  49. {
  50. ToolTipService.SetToolTip(textBlock, null);
  51. }
  52. }
  53. private static double CalcTextWidth(TextBlock textBlock)
  54. {
  55. var formattedText = TextHelper.CreateFormattedText(textBlock.Text, textBlock.FlowDirection,
  56. new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch),
  57. textBlock.FontSize);
  58. return formattedText.WidthIncludingTrailingWhitespace;
  59. }
  60. }