[WPF]文字列が表示領域に入りきらないときにポップアップで全文を表示する

WPFでの実装サンプル。
アプリの画面上で表示領域に文字列が表示しきれない場合に
オンマウスで全文がポップアップ表示されるやつ。

wholetext-popup
↑こういうやつ。

ポップアップと書いたけど、実際の実装はToolTipを使いました。

xamlのほうがスマートに書けそうな部分もあるけど、
今回はTextBlockを継承した自作コントロールを.csファイル1枚で作ってしまうイメージで
C#だけで書いてみます。

public class ToolTipTextBlock : TextBlock
{
    //コンストラクタ
    public ToolTipTextBlock()
    {
        //ツールチップに自分のTextをバインドする
        SetBinding(TextBlock.ToolTipProperty, new Binding()
        {
            RelativeSource = new RelativeSource(RelativeSourceMode.Self),
            Path = new PropertyPath("Text"),
            Mode = BindingMode.OneWay
        });

        //表示位置と表示待ち時間を調整
        SetValue(ToolTipService.HorizontalOffsetProperty, -6D);
        SetValue(ToolTipService.VerticalOffsetProperty, -2D);
        SetValue(ToolTipService.PlacementProperty, PlacementMode.Relative);
        SetValue(ToolTipService.InitialShowDelayProperty, 0);

        this.ToolTipOpening += (s, e) =>
        {
            //全文字表示されているときはツールチップを表示しない
            if (!IsTextTrimmed()) e.Handled = true;
        };
    }

    //テキストの表示がちょん切れているか確認するメソッド
    private bool IsTextTrimmed()
    {
        if (!this.IsVisible) return false;
        if (this.ActualWidth == 0) return false;

        var textEndScrPt = this.PointToScreen(new Point(this.ActualWidth - 1, 1));
        var textEndRelPt = this.PointFromScreen(textEndScrPt);

        return VisualTreeHelper.HitTest(this, textEndRelPt) == null;
    }
}

 

コードはこんだけ。

ToolTip自体は何のヘンテツもないToolTipで、
ポイントは文字列が表示しきれているかどうかの判定のとこ。
HitTestを使って、TextBlockの右上の点に要素があるかどうかを判定に利用してます。
親コントロールの領域からはみ出ているかどうかがこれで判断できる。

ただ、ToolTip自体の文字サイズとかはTextBlockと連動するわけでなくて
標準のまま固定なので、実際に使おうとするとすぐに
ToolTipのスタイルをいじりたくなるだろうと思います。
その場合はテンプレートを自分で作ることになるのかな。
↓などを参考にどうぞ。
ToolTip のスタイルとテンプレート
 

それともう1点、あまりにも残念なことに、WPFのPopUp(ToolTip)の配置設定と、
タブレット用のタッチスクリーンのOS設定がコンフリクトするらしくて、
実行環境によっては、ポップアップの表示位置が元のテキストと
全然違うところになっちゃったりすると思う。

一応、Windows8だと、実行環境のPCで直すには
コントロール パネル>ハードウェアとサウンド>タブレット PC 設定>きき手
で「右きき」/「左きき」を変えれば直ると思うんだけど、
不特定多数に向けて配布するソフトとかだと困るよなぁ。
別の手を考える必要があるかも。

→※追記:一応解決したよ!
 [WPF]Windows8で実行された際にポップアップが左右逆に出るのを防ぐ