WPF TextBlockの自動垂直スクロールバー?


335

私はTextBlockWPFにいます。縦の高さをはるかに超えて、たくさんの線を書いています。垂直スクロールバーが表示されると自動的に表示されると思っていましたが、表示されませんでした。プロパティペインでスクロールバーのプロパティを探しましたが、見つかりませんでした。

TextBlock内容が高さを超えたら、垂直スクロールバーを自動的に作成するにはどうすればよいですか?

明確化:私はむしろ、XAMLに直接書き込むのではなく、デザイナーからそれを行います。


1
この質問TextBlockTextBoxもう一度読んだとき、私はあなたが2回と1回言及したことに気づきました。
Drew Noakes、2011年

回答:


554

スクロールビューアで囲みます。

<ScrollViewer>
    <TextBlock />
</ScrollViewer>

注:この回答はTextBlock、元の質問で要求された(読み取り専用のテキスト要素)に適用されます。

TextBox(編集可能なテキスト要素)にスクロールバーを表示する場合は、ScrollViewer添付プロパティを使用します。

<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ScrollViewer.VerticalScrollBarVisibility="Auto" />

これら二つの特性のための有効な値はDisabledAutoHiddenVisible


2
デザイナーからどのようにすればよいですか?
Bab Yogoo 2009

16
すみません、わかりません。WPFデザイナーは使用していません。XAMLを直接追加すると、デザイナーはそれ自体を更新すると思います。
Drew Noakes、

5
@conqenator TextBox.ScrollToEnd();
Petey B

2
@グレッグ、問題はTextBlockないTextBoxです。
Drew Noakes、2011年

7
外側の要素が高さを強制しない場合、スクロールビューアーのMaxHeightがscollを強制的に表示するために必要になることがあります。
HackerBaloo 2017

106

今は以下を使用できます:

<TextBox Name="myTextBox" 
         ScrollViewer.HorizontalScrollBarVisibility="Auto"
         ScrollViewer.VerticalScrollBarVisibility="Auto"
         ScrollViewer.CanContentScroll="True">SOME TEXT
</TextBox>

19
@jjnguy、私は約あるとして、元の質問を解釈TextBlockしないTextBox(タイトル及び開口線のように)が、2番目の段落で言及しましたTextBox。明確にするために、この答えは間違いなくテキストボックスに最適なアプローチであり、私のものはテキストブロックに最適です:)
Drew Noakes

@Drew、ああ、理にかなっている。説明をありがとう。
jjnguy

2
私にとってもうまくいきました。少なくともTextBoxの場合、受け入れられた回答のように、その周囲でScrollViewerを使用すると、TextBoxの境界線が消えます。これは、コンテンツだけでなく、コントロール全体がスクロールされるためです。
煽ら

20

より良いものは:

<Grid Width="Your-specified-value" >
    <ScrollViewer>
         <TextBlock Width="Auto" TextWrapping="Wrap" />
    </ScrollViewer>
</Grid>

これにより、グリッドを使用しない場合のように、テキストブロック内のテキストがオーバーフローせず、テキストブロックの下の要素と重なることがなくなります。テキストブロックがすでに他の要素のグリッドにあるにもかかわらず、他の解決策を試したとき、それは私に起こりました。テキストブロックの幅はAutoである必要があり、Grid要素で希望の幅を指定する必要があることに注意してください。私は自分のコードでこれを行い、それは美しく動作します。HTH。


7
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto">
    <TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" />
</ScrollViewer>

これは、XAMLでスクロールTextBoxを使用してテキスト領域として使用する方法です。


1
質問はTextBlockないに関連していTextBoxます。
Afzaal Ahmad Zeeshan 2014年

正解は正しくありませんが、VerticalScrollBarVisibilityが有用なヒントであることがわかりました。+ 1
Malachi

4

この回答では、MVVMを使用したソリューションについて説明します。

このソリューションは、ログボックスをウィンドウに追加する場合に最適です。ログボックスは、新しいログメッセージが追加されるたびに下部に自動的にスクロールします。

これらの添付プロパティを追加すると、どこでも再利用できるため、非常にモジュール化された再利用可能なソフトウェアになります。

このXAMLを追加します。

<TextBox IsReadOnly="True"   
         Foreground="Gainsboro"                           
         FontSize="13" 
         ScrollViewer.HorizontalScrollBarVisibility="Auto"
         ScrollViewer.VerticalScrollBarVisibility="Auto"
         ScrollViewer.CanContentScroll="True"
         attachedBehaviors:TextBoxApppendBehaviors.AppendText="{Binding LogBoxViewModel.AttachedPropertyAppend}"                                       
         attachedBehaviors:TextBoxClearBehavior.TextBoxClear="{Binding LogBoxViewModel.AttachedPropertyClear}"                                    
         TextWrapping="Wrap">

この添付プロパティを追加します。

public static class TextBoxApppendBehaviors
{
    #region AppendText Attached Property
    public static readonly DependencyProperty AppendTextProperty =
        DependencyProperty.RegisterAttached(
            "AppendText",
            typeof (string),
            typeof (TextBoxApppendBehaviors),
            new UIPropertyMetadata(null, OnAppendTextChanged));

    public static string GetAppendText(TextBox textBox)
    {
        return (string)textBox.GetValue(AppendTextProperty);
    }

    public static void SetAppendText(
        TextBox textBox,
        string value)
    {
        textBox.SetValue(AppendTextProperty, value);
    }

    private static void OnAppendTextChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue == null)
        {
            return;
        }

        string toAppend = args.NewValue.ToString();

        if (toAppend == "")
        {
            return;
        }

        TextBox textBox = d as TextBox;
        textBox?.AppendText(toAppend);
        textBox?.ScrollToEnd();
    }
    #endregion
}

そして、この添付プロパティ(ボックスをクリアするため):

public static class TextBoxClearBehavior
{
    public static readonly DependencyProperty TextBoxClearProperty =
        DependencyProperty.RegisterAttached(
            "TextBoxClear",
            typeof(bool),
            typeof(TextBoxClearBehavior),
            new UIPropertyMetadata(false, OnTextBoxClearPropertyChanged));

    public static bool GetTextBoxClear(DependencyObject obj)
    {
        return (bool)obj.GetValue(TextBoxClearProperty);
    }

    public static void SetTextBoxClear(DependencyObject obj, bool value)
    {
        obj.SetValue(TextBoxClearProperty, value);
    }

    private static void OnTextBoxClearPropertyChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs args)
    {
        if ((bool)args.NewValue == false)
        {
            return;
        }

        var textBox = (TextBox)d;
        textBox?.Clear();
    }
}   

次に、MEFなどの依存関係注入フレームワークを使用している場合は、ロギング固有のすべてのコードを独自のViewModelに配置できます。

public interface ILogBoxViewModel
{
    void CmdAppend(string toAppend);
    void CmdClear();

    bool AttachedPropertyClear { get; set; }

    string AttachedPropertyAppend { get; set; }
}

[Export(typeof(ILogBoxViewModel))]
public class LogBoxViewModel : ILogBoxViewModel, INotifyPropertyChanged
{
    private readonly ILog _log = LogManager.GetLogger<LogBoxViewModel>();

    private bool _attachedPropertyClear;
    private string _attachedPropertyAppend;

    public void CmdAppend(string toAppend)
    {
        string toLog = $"{DateTime.Now:HH:mm:ss} - {toAppend}\n";

        // Attached properties only fire on a change. This means it will still work if we publish the same message twice.
        AttachedPropertyAppend = "";
        AttachedPropertyAppend = toLog;

        _log.Info($"Appended to log box: {toAppend}.");
    }

    public void CmdClear()
    {
        AttachedPropertyClear = false;
        AttachedPropertyClear = true;

        _log.Info($"Cleared the GUI log box.");
    }

    public bool AttachedPropertyClear
    {
        get { return _attachedPropertyClear; }
        set { _attachedPropertyClear = value; OnPropertyChanged(); }
    }

    public string AttachedPropertyAppend
    {
        get { return _attachedPropertyAppend; }
        set { _attachedPropertyAppend = value; OnPropertyChanged(); }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

仕組みは次のとおりです。

  • ViewModelは、添付プロパティを切り替えて、TextBoxを制御します。
  • 「追加」を使用しているため、非常に高速です。
  • 他のViewModelは、ロギングViewModelのメソッドを呼び出すことにより、ロギングメッセージを生成できます。
  • TextBoxに組み込まれているScrollViewerを使用するので、新しいメッセージが追加されるたびに、テキストボックスの下部まで自動的にスクロールできます。

4
<ScrollViewer MaxHeight="50"  
              Width="Auto" 
              HorizontalScrollBarVisibility="Disabled"
              VerticalScrollBarVisibility="Auto">
     <TextBlock Text="{Binding Path=}" 
                Style="{StaticResource TextStyle_Data}" 
                TextWrapping="Wrap" />
</ScrollViewer>

MaxHeightをScrollViewerに配置することで、別の方法でこれを行っています。

MaxHeightを調整して、表示するテキストの行数を増減します。簡単です。



1

私はこれらの提案をテキストブロックで機能するようにしようとしましたが、機能しませんでした。私はそれをデザイナーから機能させることさえ試みました。(レイアウトを見て、一番下にある下向き矢印「V」をクリックしてリストを展開)私はScrollViewerの設定しようとした目に見えるし、その後オート、それはまだ動作しません。

最終的にはあきらめ、Readonly属性を設定したTextBlockをaに変更しました。TextBox


0

他の誰かがこの問題を持っていますが、私を包む場合はいけない知っているTextBlockScrollViewer単純な私は交換することを考え出した回避策として-私のUIを台無しsomewhow TextBlockによってTextBox、この1のように

<TextBox  Name="textBlock" SelectionBrush="Transparent" Cursor="Arrow" IsReadOnly="True" Text="My Text" VerticalScrollBarVisibility="Auto">

は、スクロールバーを備えたのTextBoxように見え、動作するを作成しTextBlockます(デザイナですべて実行できます)。


0

これはその質問に対する簡単な解決策です。垂直スクロールは、テキストがオーバーフローしたときにのみアクティブになります。

<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.