WPF 中 TextBlock 设置TextTrimming 后,并根据需要自动显示 ToolTip
第一种方式:在 TextBlock 中使用附加属性
实现 TextBlockUtils 类,定义 AutoTooltip 附加属性
:
public class TextBlockUtils { /// <summary> /// Gets the value of the AutoTooltipProperty dependency property /// </summary> public static bool GetAutoTooltip(DependencyObject obj) { return (bool)obj.GetValue(AutoTooltipProperty); } /// <summary> /// Sets the value of the AutoTooltipProperty dependency property /// </summary> public static void SetAutoTooltip(DependencyObject obj, bool value) { obj.SetValue(AutoTooltipProperty, value); } /// <summary> /// Identified the attached AutoTooltip property. When true, this will set the TextBlock TextTrimming /// property to WordEllipsis, and display a tooltip with the full text whenever the text is trimmed. /// </summary> public static readonly DependencyProperty AutoTooltipProperty = DependencyProperty.RegisterAttached("AutoTooltip", typeof(bool), typeof(TextBlockUtils), new PropertyMetadata(false, OnAutoTooltipPropertyChanged)); private static void OnAutoTooltipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock textBlock = d as TextBlock; if (textBlock == null) return; if (e.NewValue.Equals(true)) { textBlock.TextTrimming = TextTrimming.WordEllipsis; ComputeAutoTooltip(textBlock); textBlock.SizeChanged += TextBlock_SizeChanged; } else { textBlock.SizeChanged -= TextBlock_SizeChanged; } } private static void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e) { TextBlock textBlock = sender as TextBlock; ComputeAutoTooltip(textBlock); } /// <summary> /// Assigns the ToolTip for the given TextBlock based on whether the text is trimmed /// </summary> private static void ComputeAutoTooltip(TextBlock textBlock) { #if !Silverlight textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); var width = textBlock.DesiredSize.Width; if (textBlock.ActualWidth < width) { ToolTipService.SetToolTip(textBlock, textBlock.Text); } else { ToolTipService.SetToolTip(textBlock, null); } #else FrameworkElement parentElement = VisualTreeHelper.GetParent(textBlock) as FrameworkElement; if (parentElement != null) { if (textBlock.ActualWidth > parentElement.ActualWidth) { ToolTipService.SetToolTip(textBlock, textBlock.Text); } else { ToolTipService.SetToolTip(textBlock, null); } } #endif } }
xaml 代码中使用:
先在 xaml 首行添加 TextBlockUtils 类的命名空间:xmlns:util="clr-namespace:DriverEasyWPF.Utils”
然后将 Textblock 的 TextTrimming 属性设置为 true;
<Grid MaxWidth="200"> <TextBlock Text="A few weeks ago, I blogged about a Silverlight solution for automatically adding tooltips when a TextBlock Text is trimmed and renders an ellipsis. I found a decent looking WPF solutions on the web and linked it in my article" VerticalAlignment="Center" TextTrimming="WordEllipsis" util:TextBlockUtils.AutoTooltip="True"/> </Grid>
第二种方式,使用转换器来实现
实现转换器 TrimmedTextBlockVisibilityConverter 类:
public class TrimmedTextBlockVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null || value == DependencyProperty.UnsetValue) return Visibility.Collapsed; FrameworkElement textBlock = (FrameworkElement)value; textBlock.Measure(new System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity)); if (((FrameworkElement)value).ActualWidth < ((FrameworkElement)value).DesiredSize.Width) return Visibility.Visible; else return Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
在 App.xaml 中声明转换器:
<convert:TrimmedTextBlockVisibilityConverter x:Key="TrimmedTextBlockVisibilityConverter"/>
在 xaml 中使用:
将 Textblock 的 TextTrimming 属性设置为 true;
<Grid MaxWidth="395"> <TextBlock Text="A few weeks ago, I blogged about a Silverlight solution for automatically adding tooltips when a TextBlock Text is trimmed and renders an ellipsis. I found a decent looking WPF solutions on the web and linked it in my article" VerticalAlignment="Center" TextTrimming="WordEllipsis"> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="#333"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="Foreground" Value="#22acff"/> </Trigger> </Style.Triggers> </Style> </TextBlock.Style> <TextBlock.ToolTip> <ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource TrimmedTextBlockVisibilityConverter}}" Content="A few weeks ago, I blogged about a Silverlight solution for automatically adding tooltips when a TextBlock Text is trimmed and renders an ellipsis. I found a decent looking WPF solutions on the web and linked it in my article"> </ToolTip> </TextBlock.ToolTip> </TextBlock> </Grid>
注意:
使用附加属性的方式,如果在 ListBox 的 items 中 TextBlock 使用,如果 items 数量过大,界面可能会出现 1 秒左右的卡顿,才会显示最终效果。
使用转换器的方式就没有这个问题。
参考: