在Windows应用商店应用程序中,我有以下TextBlock:
<TextBlock Text="Seriously long text for the purpose of showing tooltip" TextTrimming="CharacterEllipsis" />
如果文本太长,没有省略号就无法显示,如何自动显示工具提示?
clj7thdc1#
这是我的解决方案,基于this和this。首先,创建一个附加属性以启用自动工具提示:
public static class TextBlockUtils { public static readonly DependencyProperty AutoTooltipProperty = DependencyProperty.RegisterAttached ("AutoTooltip", typeof (bool), typeof (TextBlockUtils), new PropertyMetadata (false, OnAutoTooltipPropertyChanged)); public static void SetAutoTooltip (DependencyObject d, bool value) { d.SetValue (AutoTooltipProperty, value); } public static bool GetAutoTooltip (DependencyObject d) { return (bool) d.GetValue (AutoTooltipProperty); } private static void OnAutoTooltipPropertyChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) { var tb = d as TextBlock; if (tb != null) { bool newValue = (bool) e.NewValue; if (newValue) { SetTooltipBasedOnTrimmingState (tb); tb.SizeChanged += OnTextBlockSizeChanged; } else { tb.SizeChanged -= OnTextBlockSizeChanged; } } } private static void OnTextBlockSizeChanged (object sender, SizeChangedEventArgs e) { var tb = sender as TextBlock; if (tb != null) { SetTooltipBasedOnTrimmingState (tb); } } private static void SetTooltipBasedOnTrimmingState (TextBlock tb) { bool isTextTrimmed = tb.ActualWidth < tb.DesiredSize.Width; ToolTipService.SetToolTip (tb, isTextTrimmed ? tb.Text : null); } }
然后在XAML中使用它,如下所示:
<TextBlock Content="long text" TextTrimming="CharacterEllipsis" TextBlockUtils.AutoTooltip="True" />
工具提示只会在文本块被修剪时显示。
txu3uszq2#
通常你点击它,打开一个视图,它会完整地显示出来,要么是因为它有更多的空间/使用更小的字体,要么是文本换行/滚动。
cld4siwp3#
以下是我基于pogosama回答的两点看法。当重用TextBlock时,我必须检测文本更改,因为大小更改是不够的。关键是:ToolTipService.SetIsEnabled(tb, isTextTrimmed);OnTextBlockSizeChanged用于两种情况,因为OnToolTipTextChanged之前被调用,因此FormattedText还没有被计算。
ToolTipService.SetIsEnabled(tb, isTextTrimmed);
OnTextBlockSizeChanged
OnToolTipTextChanged
FormattedText
public static class TextBlockUtils { /// <summary> /// Used by the simple version /// </summary> public static readonly DependencyProperty ToolTipTextProperty = DependencyProperty.RegisterAttached("ToolTipText", typeof(string), typeof(TextBlockUtils), new PropertyMetadata(null, OnToolTipTextChanged)); public static string GetToolTipText(DependencyObject obj) => (string)obj.GetValue(ToolTipTextProperty); public static void SetToolTipText(DependencyObject obj, string value) => obj.SetValue(ToolTipTextProperty, value); public static readonly DependencyProperty HasSubscribedProperty = DependencyProperty.RegisterAttached("HasSubscribed", typeof(bool), typeof(TextBlockUtils), new PropertyMetadata(false, null)); public static bool GetHasSubscribed(DependencyObject d) => (bool)d.GetValue(HasSubscribedProperty); public static void SetHasSubscribed(DependencyObject d, bool value) => d.SetValue(HasSubscribedProperty, value); /// <summary> /// Used by the templated version /// </summary> public static readonly DependencyProperty AutoToolTipProperty = DependencyProperty.RegisterAttached("AutoToolTip", typeof(bool), typeof(TextBlockUtils), new PropertyMetadata(false, OnAutoToolTipPropertyChanged)); public static bool GetAutoToolTip(DependencyObject d) => (bool)d.GetValue(AutoToolTipProperty); public static void SetAutoToolTip(DependencyObject d, bool value) => d.SetValue(AutoToolTipProperty, value); private static void OnToolTipTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock tb = d as TextBlock; if (!GetHasSubscribed(tb))//anti multi subscribe { tb.SizeChanged -= OnTextBlockSizeChanged; tb.SizeChanged += OnTextBlockSizeChanged; SetHasSubscribed(tb, true); } SetToolTipBasedOnTrimmingState(tb); } private static void OnAutoToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var tb = d as TextBlock; bool newValue = (bool)e.NewValue; if (newValue) { SetToolTipBasedOnTrimmingState(tb); tb.SizeChanged += OnTextBlockSizeChanged; } else { tb.SizeChanged -= OnTextBlockSizeChanged; } } private static void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e) { var tb = sender as TextBlock; SetToolTipBasedOnTrimmingState(tb); } private static void SetToolTipBasedOnTrimmingState(TextBlock tb) { Typeface typeface = new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch); FormattedText formattedText = new FormattedText(tb.Text, System.Threading.Thread.CurrentThread.CurrentCulture, tb.FlowDirection, typeface, tb.FontSize, tb.Foreground) { MaxTextWidth = tb.ActualWidth }; bool isTextTrimmed = (formattedText.Height > tb.ActualHeight || formattedText.MinWidth > formattedText.MaxTextWidth); ToolTipService.SetIsEnabled(tb, isTextTrimmed);//because ToolTipService.ShowOnDisabledProperty = false, this works object templatedToolTip = tb.FindName("TemplatedToolTip"); if (templatedToolTip != null && templatedToolTip is ToolTip) { ToolTip toolTip = templatedToolTip as ToolTip; tb.ToolTip = toolTip; } else tb.ToolTip = GetToolTipText(tb); } }
简单版本
<TextBlock Text={Binding MyText} utils:TextBlockUtils.ToolTipText="{Binding Text, RelativeSource={RelativeSource Self}, Mode=OneWay}" TextTrimming="WordEllipsis"> or <TextBlock Text={Binding MyText} utils:TextBlockUtils.ToolTipText="{Binding Whatever}" TextTrimming="WordEllipsis">
模板化版本
<TextBlock Text="{Binding Comment.CommentText, FallbackValue=Comment}" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" utils:TextBlockUtils.AutoToolTip="True"> <TextBlock.ToolTip> <ToolTip x:Name="TemplatedToolTip" Placement="Bottom"> <ToolTip.Template> <ControlTemplate> <Border> <TextBlock TextWrapping="Wrap"> <Run Text="Event :" FontStyle="Italic" FontWeight="Bold"/> <LineBreak/> <Run Text="{Binding Whatever}"/> <LineBreak/> <Run Text="{Binding Comment.CommentText}"/> </TextBlock> </Border> </ControlTemplate> </ToolTip.Template> </ToolTip> </TextBlock.ToolTip> </TextBlock>
3条答案
按热度按时间clj7thdc1#
这是我的解决方案,基于this和this。
首先,创建一个附加属性以启用自动工具提示:
然后在XAML中使用它,如下所示:
工具提示只会在文本块被修剪时显示。
txu3uszq2#
通常你点击它,打开一个视图,它会完整地显示出来,要么是因为它有更多的空间/使用更小的字体,要么是文本换行/滚动。
cld4siwp3#
以下是我基于pogosama回答的两点看法。
当重用TextBlock时,我必须检测文本更改,因为大小更改是不够的。
关键是:
ToolTipService.SetIsEnabled(tb, isTextTrimmed);
OnTextBlockSizeChanged
用于两种情况,因为OnToolTipTextChanged
之前被调用,因此FormattedText
还没有被计算。简单版本
模板化版本