none
C# WPF RichTextBoxのScrollBar の表示の有無の状態を知りたい RRS feed

  • 質問

  • 現在C# 2015 にて WPFアプリ を作成しています.

    現在C# 2015 にて WPFアプリ を作成しています.

    大きさ一定のRichTextBoxがあり、そこにTextを流し込もうとしています。
    で、このRichTextBoxにtextが入りきらない場合は、文字フォントを小さくして、全部の表示をさせる機能を作成しています。以下 話を簡単にするため、縦方向だけに限定させていただきます。

    Xamlにて、RichTextBoxには、VerticalScrollBarVisibility="Auto" 設定してあります。
    <RichTextBox VerticalScrollBarVisibility="Auto" />

    RichTextBoxに全文が入りきれない場合は、視覚では、上記のScrollBarが表示され判断できるのですが、
    コーディング上から確認できる、method , property はないのでしょうか

    お分かりになられる方がいらっしゃいましたら、何卒ご教授宜しく御願い致します.


    なお、現在の方法は、下記のように、textのsizeを測定し、この縦方向の値と、RichTextBoxの大きさと比較して
    行溢れを検出しています。がどうもスッキリしません。

            public static Size MeasureString(string text, double fontSize, string typeFace)
            {
                if (text != null && fontSize != 0)
                {
                    var ft = new FormattedText(text, CultureInfo.CurrentCulture,
                    FlowDirection.LeftToRight,
                    new Typeface(typeFace),
                    fontSize,
                    Brushes.White);

                    return new Size(ft.Width, ft.Height);
                }
                else
                    return new Size(0.0, 0.0);
            }

    なお、文字はカラー化が必要ですので、TextBoxでの適用は考えていません。

    ネットを探し回ると、ScrollViewerコントロールには、ScrollToBottom()があり、これにより、VerticalOffsetの値で
    比較すれば、行溢れを検出できるのかと思うのですが、どうなんでしょうか
    2018年2月12日 6:44

回答

  • RichTextBox内のScrollBarもしくはScrollViewerを捕まえてやれば、変化した時をイベントで把握することはできます。
    <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <RichTextBox VerticalScrollBarVisibility="Auto">
                <RichTextBox.Resources>
                    <Style TargetType="{x:Type ScrollBar}">
                        <EventSetter Event="Loaded" Handler="ScrollBar_Loaded" />
                    </Style>
                    <Style TargetType="{x:Type ScrollViewer}">
                        <EventSetter Event="Loaded" Handler="ScrollViewer_Loaded" />
                    </Style>
                </RichTextBox.Resources>
            </RichTextBox>
        </Grid>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void ScrollBar_Loaded(object sender, RoutedEventArgs e)
            {
                var sb = (System.Windows.Controls.Primitives.ScrollBar)sender;
                if (sb.TemplatedParent is ScrollViewer)
                {
                    var sv=(ScrollViewer)sb.TemplatedParent;
                    if (sv.TemplatedParent is RichTextBox)
                    {
                        sb.IsVisibleChanged += Sb_IsVisibleChanged;
                    }
                }
            }
    
            private void Sb_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                //スクロールバーが表示されているかだけ判断したいなら
                var sb = (System.Windows.Controls.Primitives.ScrollBar)sender;
                System.Diagnostics.Debug.WriteLine("ScrollBar.IsVisible=" + sb.IsVisible);
            }
    
            /*---------------------------*/
    
            private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
            {
                var sv = (ScrollViewer)sender;
                if (sv.TemplatedParent is RichTextBox)
                {
                    sv.ScrollChanged += Sv_ScrollChanged;
                }
            }
    
            private void Sv_ScrollChanged(object sender, ScrollChangedEventArgs e)
            {
                //スクロール範囲などをを知りたいなら
                var sv = (ScrollViewer)sender;
                System.Diagnostics.Debug.WriteLine("全体高さ={0},見える高さ={1},スクロールバー={2}", sv.ExtentHeight, sv.ViewportHeight, (sv.ScrollableHeight > 0).ToString());
            }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク エンバー 2018年2月13日 12:11
    2018年2月12日 10:01

すべての返信

  • RichTextBox内のScrollBarもしくはScrollViewerを捕まえてやれば、変化した時をイベントで把握することはできます。
    <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <RichTextBox VerticalScrollBarVisibility="Auto">
                <RichTextBox.Resources>
                    <Style TargetType="{x:Type ScrollBar}">
                        <EventSetter Event="Loaded" Handler="ScrollBar_Loaded" />
                    </Style>
                    <Style TargetType="{x:Type ScrollViewer}">
                        <EventSetter Event="Loaded" Handler="ScrollViewer_Loaded" />
                    </Style>
                </RichTextBox.Resources>
            </RichTextBox>
        </Grid>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void ScrollBar_Loaded(object sender, RoutedEventArgs e)
            {
                var sb = (System.Windows.Controls.Primitives.ScrollBar)sender;
                if (sb.TemplatedParent is ScrollViewer)
                {
                    var sv=(ScrollViewer)sb.TemplatedParent;
                    if (sv.TemplatedParent is RichTextBox)
                    {
                        sb.IsVisibleChanged += Sb_IsVisibleChanged;
                    }
                }
            }
    
            private void Sb_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                //スクロールバーが表示されているかだけ判断したいなら
                var sb = (System.Windows.Controls.Primitives.ScrollBar)sender;
                System.Diagnostics.Debug.WriteLine("ScrollBar.IsVisible=" + sb.IsVisible);
            }
    
            /*---------------------------*/
    
            private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
            {
                var sv = (ScrollViewer)sender;
                if (sv.TemplatedParent is RichTextBox)
                {
                    sv.ScrollChanged += Sv_ScrollChanged;
                }
            }
    
            private void Sv_ScrollChanged(object sender, ScrollChangedEventArgs e)
            {
                //スクロール範囲などをを知りたいなら
                var sv = (ScrollViewer)sender;
                System.Diagnostics.Debug.WriteLine("全体高さ={0},見える高さ={1},スクロールバー={2}", sv.ExtentHeight, sv.ViewportHeight, (sv.ScrollableHeight > 0).ToString());
            }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク エンバー 2018年2月13日 12:11
    2018年2月12日 10:01
  • gekka さま

    早速の回答ありがとううございます。

    いけそうですね

    当方、MVVM(Livet + ReactiveProperty) でやっているため、そちらにソースを直して、確認したいと思います。

    ただ、万年初心者のためできるかどうかは自信ありませんが・・・

    とりあえずはお礼まで


    2018年2月12日 12:32
  • gekka さま エンバーです。

    MVVM(4,5時間からかったのですが)をあきらめて、gekka さまのソースのまま実行しました。

    ばっちり動作しました。

    大変ありがとうございました。

    また、副産物で、いままで、ExtenHeight(下記、全体高さ)が理解できなかったのですが、今回のdebug.print文の結果により理解出来ました。

    ----------

    1.フォント12 改行8か所あり
    全体高さ=802.32,見える高さ=745.26,スクロールバー=True,バー移動可能=57,RTB高さ=745.26
    2.フォント12 改行なし
    全体高さ=672.72,見える高さ=728.26,スクロールバー=False,バー移動可能=0,RTB高さ=745.26

    3.フォント10 改行8か所あり
    全体高さ=689.52,見える高さ=745.26,スクロールバー=False,バー移動可能=0,RTB高さ=745.26
    4.フォント10 改行なし
    全体高さ=511.92,見える高さ=745.26,スクロールバー=False,バー移動可能=0,RTB高さ=745.26

    -------

    また、見える高さ(ViewportHeight)のところ、2のときだけ、RTB高さと同一にならず、理解に苦しみますが、

    あとは、見える高さ=RTB高さなので、良しとします。

    どうもありがとうございました。

    2018年2月13日 6:17
  • エンバーさん、こんにちは。フォーラム オペレーターの立花です。

    gekka さんからの返信はご参考になりましたでしょうか。
    参考となった投稿がありましたら [回答としてマーク] を設定いただき、
    同じ問題でお困りの方へも情報をご共有くださいね。

    ご協力の程、どうかよろしくお願いいたします。


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    2018年2月13日 6:23
    モデレータ