WPF TextBlock의 자동 세로 스크롤 막대?


336

나는이 TextBlockWPF에. 수직 높이를 훨씬 초과하여 많은 행을 씁니다. 그런 일이 발생하면 세로 스크롤 막대가 자동으로 나타날 것으로 예상했지만 그렇지 않았습니다. 속성 창에서 스크롤 막대 속성을 찾으려고했지만 찾을 수 없습니다.

TextBlock내용물이 높이를 초과 하면 세로 스크롤 막대가 자동으로 만들어 지려면 어떻게해야합니까?

설명 : 나는 XAML에 직접 쓰는 것이 아니라 디자이너로부터 그것을하고 싶습니다.


1
이 질문을 다시 읽으면 TextBlock두 번 언급 한 것을 알 수 있습니다 TextBox.
Drew Noakes

답변:


555

스크롤 뷰어로 감싸십시오.

<ScrollViewer>
    <TextBlock />
</ScrollViewer>

참고이 답변 TextBlock은 원래 질문에서 요구 한대로 (읽기 전용 텍스트 요소)에 적용됩니다 .

TextBox(편집 가능한 텍스트 요소) 에 스크롤 막대를 표시 하려면 ScrollViewer연결된 속성 을 사용하십시오 .

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

이 두 가지 속성에 대한 유효한 값은 Disabled, Auto, HiddenVisible.


2
디자이너로부터 어떻게합니까?
밥 Yogoo

16
확실하지 않습니다. WPF 디자이너를 사용하지 않습니다. XAML을 직접 추가하면 디자이너가 자체적으로 업데이트한다고 생각합니다.
Drew Noakes

5
@conqenator TextBox.ScrollToEnd ();
Petey B

2
@Greg, 질문은 TextBlock아닙니다 TextBox.
Drew Noakes

7
때로는 둘러싼 요소가 높이를 강요하지 않는 경우 ScrollViewer의 MaxHeight가 scoll을 강제로 표시해야합니다.
HackerBaloo

106

지금 다음을 사용할 수 있습니다 :

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

19
@jjnguy, 나는 원래의 질문을 제목과 오프닝 라인과 같이 TextBlock하지 않은 것으로 해석 TextBox했지만 두 번째 단락은 언급했습니다 TextBox. 분명히,이 답변은 확실히 텍스트 상자에 가장 적합한 방법 이며, 내 텍스트 블록 에 대해 가장 잘 알고 있습니다. :)
Drew Noakes

@Drew는 아 이해가됩니다. 설명해 주셔서 감사합니다.
jjnguy

2
나도 더 잘했다. 적어도 TextBox의 경우 허용되는 답변과 같이 주위에 ScrollViewer를 사용하면 내용뿐만 아니라 전체 컨트롤이 스크롤되므로 TextBox의 테두리가 사라집니다.
연료

20

더 나은 것 :

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

이렇게하면 그리드를 사용하지 않는 경우와 같이 텍스트 블록의 텍스트가 오버플로되지 않고 텍스트 블록 아래의 요소와 겹치지 않습니다. 텍스트 블록이 이미 다른 요소와 그리드에 있었지만 다른 솔루션을 시도했을 때 나에게 일어났습니다. 텍스트 블록의 너비는 자동이어야하며 그리드 요소에서 원하는 것을 지정해야합니다. 내 코드 에서이 작업을 수행했으며 아름답게 작동합니다. HTH.


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

XAML에서 스크롤하는 TextBox를 사용하여 텍스트 영역으로 사용하는 방법입니다.


1
질문은와 관련이 TextBlock없습니다 TextBox.
Afzaal Ahmad Zeeshan 2016

정답은 아니지만, 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를 제어합니다.
  • "Append"를 사용함에 따라 번개가 빠릅니다.
  • 다른 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를 Visible로 설정 한 다음 Auto 로 설정하려고 시도 했지만 여전히 작동하지 않습니다.

나는 결국 읽기 전용 속성 집합을 사용 하여 TextBlock를 포기 하고 매력처럼 작동했습니다.TextBox


0

다른 사람 이이 문제를 겪고 있는지 모르지만 어떻게 든 내 UI를 어쨌든 내 UI를 엉망 TextBlock으로 ScrollViewer만들었습니다. 간단한 해결 방법으로TextBlock a로 TextBox이와 같은

<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.