24
  <TextBlock Width="100" Text="The quick brown fox jumps over the lazy dog" TextTrimming="WordEllipsis">
     <TextBlock.ToolTip>
        <ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
           <TextBlock Text="{Binding Text}"/>
        </ToolTip>
     </TextBlock.ToolTip>
  </TextBlock>

ToolTipテキストがトリミングされたときにのみ表示するにはどうすればよいですか? Windows デスクトップのショートカット アイコンと同様です。

4

7 に答える 7

7

行動は愛であり、行動は人生です。

public class TextBlockAutoToolTipBehavior : Behavior<TextBlock>
{
    private ToolTip _toolTip;

    protected override void OnAttached()
    {
        base.OnAttached();
        _toolTip = new ToolTip
        {
            Placement = PlacementMode.Relative,
            VerticalOffset = 0,
            HorizontalOffset = 0
        };

        ToolTipService.SetShowDuration(_toolTip, int.MaxValue);

        _toolTip.SetBinding(ContentControl.ContentProperty, new Binding
        {
            Path = new PropertyPath("Text"),
            Source = AssociatedObject
        });

        AssociatedObject.TextTrimming = TextTrimming.CharacterEllipsis;
        AssociatedObject.AddValueChanged(TextBlock.TextProperty, TextBlockOnTextChanged);
        AssociatedObject.SizeChanged += AssociatedObjectOnSizeChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.RemoveValueChanged(TextBlock.TextProperty, TextBlockOnTextChanged);
        AssociatedObject.SizeChanged -= AssociatedObjectOnSizeChanged;
    }

    private void AssociatedObjectOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
    {
        CheckToolTipVisibility();
    }

    private void TextBlockOnTextChanged(object sender, EventArgs eventArgs)
    {
        CheckToolTipVisibility();
    }

    private void CheckToolTipVisibility()
    {
        if (AssociatedObject.ActualWidth == 0)
            Dispatcher.BeginInvoke(
                new Action(
                    () => AssociatedObject.ToolTip = CalculateIsTextTrimmed(AssociatedObject) ? _toolTip : null),
                DispatcherPriority.Loaded);
        else
            AssociatedObject.ToolTip = CalculateIsTextTrimmed(AssociatedObject) ? _toolTip : null;
    }

    //Source: https://stackoverflow.com/questions/1041820/how-can-i-determine-if-my-textblock-text-is-being-trimmed
    private static bool CalculateIsTextTrimmed(TextBlock textBlock)
    {
        Typeface typeface = new Typeface(
            textBlock.FontFamily,
            textBlock.FontStyle,
            textBlock.FontWeight,
            textBlock.FontStretch);

        // FormattedText is used to measure the whole width of the text held up by TextBlock container
        FormattedText formattedText = new FormattedText(
            textBlock.Text,
            System.Threading.Thread.CurrentThread.CurrentCulture,
            textBlock.FlowDirection,
            typeface,
            textBlock.FontSize,
            textBlock.Foreground) {MaxTextWidth = textBlock.ActualWidth};


        // When the maximum text width of the FormattedText instance is set to the actual
        // width of the textBlock, if the textBlock is being trimmed to fit then the formatted
        // text will report a larger height than the textBlock. Should work whether the
        // textBlock is single or multi-line.
        // The width check detects if any single line is too long to fit within the text area, 
        // this can only happen if there is a long span of text with no spaces.
        return (formattedText.Height > textBlock.ActualHeight || formattedText.MinWidth > formattedText.MaxTextWidth);
    }
}

使用法:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:behavior="clr-namespace:MyWpfApplication.Behavior"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <TextBlock Text="{Binding Text}">
        <i:Interaction.Behaviors>
            <behavior:TextBlockAutoToolTipBehavior />
        </i:Interaction.Behaviors>
    </TextBlock>
</Window>

必要な拡張メソッド:

public static class UITools
{
    public static void AddValueChanged<T>(this T obj, DependencyProperty property, EventHandler handler)
        where T : DependencyObject
    {
        var desc = DependencyPropertyDescriptor.FromProperty(property, typeof (T));
        desc.AddValueChanged(obj, handler);
    }

    public static void RemoveValueChanged<T>(this T obj, DependencyProperty property, EventHandler handler)
        where T : DependencyObject
    {
        var desc = DependencyPropertyDescriptor.FromProperty(property, typeof (T));
        desc.RemoveValueChanged(obj, handler);
    }
}
于 2016-11-21T13:45:11.983 に答える
2

コンバーターや派生 TextBlock コントロールを使用するよりも優れていると思います

于 2015-09-18T15:07:10.350 に答える
2

ActualWidthtextblockとの を比較しDesiredSize.Width、 を返すコンバーターを作成できると思いますVisibility

于 2011-06-14T10:33:31.113 に答える