it-swarm.com.ru

Автоматическая вертикальная полоса прокрутки в WPF TextBlock?

У меня есть TextBlock в WPF. Я пишу много строк, намного превышающих его вертикальную высоту. Я ожидал, что вертикальная полоса прокрутки появится автоматически, когда это произойдет, но это не так. Я попытался найти свойство полосы прокрутки на панели свойств, но не смог найти его.

Как сделать так, чтобы вертикальная полоса прокрутки создавалась автоматически для моей TextBlock, когда ее содержимое превышает ее высоту?

Пояснение: я бы предпочел сделать это от дизайнера, а не напрямую писать в XAML.

294
Bab Yogoo

Оберните это в просмотрщик прокрутки:

<ScrollViewer>
    <TextBlock />
</ScrollViewer>

NOTEэтот ответ применяется к TextBlock (текстовый элемент только для чтения), как было запрошено в исходном вопросе.

Если вы хотите отобразить полосы прокрутки в TextBox (редактируемый текстовый элемент), тогда используйте вложенные свойства ScrollViewer:

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

Допустимые значения для этих двух свойств: Disabled, Auto, Hidden и Visible.

501
Drew Noakes

можете использовать следующее сейчас:

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

Что-то лучше было бы:

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

Это гарантирует, что текст в вашем текстовом блоке не переполняется и не перекрывает элементы ниже текстового блока, как это может быть в случае, если вы не используете сетку. Это случилось со мной, когда я попробовал другие решения, хотя текстовый блок уже был в сетке с другими элементами. Имейте в виду, что ширина текстового блока должна быть Авто, и вы должны указать желаемое значение в элементе Grid. Я сделал это в своем коде, и это прекрасно работает. НТН.

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

Это способ использовать прокручиваемый TextBox в XAML и использовать его как текстовую область.

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

Я делаю это по-другому, помещая MaxHeight в ScrollViewer.

Просто настройте MaxHeight, чтобы показать больше или меньше строк текста. Легко.

3
Tony Wu

Этот ответ описывает решение с использованием 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 ведения журнала.
  • Поскольку мы используем ScrollViewer, встроенный в TextBox, мы можем автоматически прокручивать его до конца текстового поля каждый раз, когда добавляется новое сообщение.
3
Contango

Ты можешь использовать

ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"

Это свойство wpf . Для получения дополнительной информации

http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html

2
ravi saini

Я пытался заставить эти предложения работать для текстового блока, но не смог заставить его работать. Я даже пытался заставить его работать у дизайнера. (Посмотрите в Макете и разверните список, нажав стрелку вниз «V» внизу). Я попытался установить для просмотра прокрутки значение Видимый , а затем Авто , но оно все равно не сработало. 

В конце концов я сдался и изменил TextBlock на TextBox с набором атрибутовReadonly, и это сработало как шарм. 

1
Scott Bordelon

Не знаю, есть ли у кого-то еще эта проблема, но обертывание моего TextBlock в ScrollViewer каким-то образом испортило мой пользовательский интерфейс - как простой обходной путь, я выяснил, что замена TextBlock на TextBox как этот

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

создает TextBox, который выглядит и ведет себя как TextBlock с полосой прокрутки (и вы можете сделать все это в конструкторе).

0
dunkleosteus

Это простое решение этого вопроса. Вертикальная прокрутка будет активирована только при переполнении текста.

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

0
Zuhair