読者です 読者をやめる 読者になる 読者になる

みかづきメモ

学習したことのメモとか、日記とか、備忘録。

WPFで、コンテンツエリアがいっぱいになった時にだけ ToolTip を表示する

WPF で例えば下みたいなとき

<TextBlock Width="200"
           Text="very very very very very very very long text"
           TextTrimming="CharacterEllipsis" />

こんなかんじで、範囲を超えた分は「...」と表示されます。
f:id:MikazukiFuyuno:20150822230529p:plain

そういった時だけ、 ToolTip を表示する方法です。

まず下のような Behavior を作っておきます。

using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace Experiment.Wpf.Behaviors
{
    /// <summary>
    /// TextBlock.Text が描画幅を超えている際に、 TextBlock.Text の内容を ToolTip で表示するようにします。
    /// (Text が Trimming されている時のみ、 ToolTip を表示します)
    /// </summary>
    public class TextBlockToolTipBehavior : Behavior<TextBlock>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged;
            base.OnDetaching();
        }

        private void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var text = (TextBlock)sender;
            var formattedText = new FormattedText(text.Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                new Typeface(text.FontFamily, text.FontStyle, text.FontWeight, text.FontStretch), text.FontSize,
                text.Foreground);

            if (text.ActualWidth < formattedText.Width)
            {
                var tooltip = new TextBlock
                {
                    Text = text.Text
                };
                text.ToolTip = tooltip;
            }
            else
                text.ToolTip = null;
        }
    }
}

んで、適用する。

<TextBlock Width="200"
           Text="very very very very very very very long text"
           TextTrimming="CharacterEllipsis">
    <i:Interaction.Behaviors>
        <b:TextBlockToolTipBehavior />
    </i:Interaction.Behaviors>
</TextBlock>

こんな感じにすれば、「...」って省略されてる時だけ ToolTip が表示されます。

仕組みは単純で、描画されている幅 ActualWidth
テキストの幅 FormattedText.Width よりも小さい時だけ、ToolTip を設定します。

また、サイズの変更を受け取っておくことで、例えばウィンドウサイズが変わって「...」と
省略されなくなった時はToolTip を表示しないようにしています。

ではでは

こっちのほうがいいよ!みたいなのあったら、コメントください!