Автоматическая вертикальная полоса прокрутки в текстовом блоке WPF?
у меня есть TextBlock в WPF. Я пишу ему много строк, намного превышающих его вертикальную высоту. Я ожидал, что вертикальная полоса прокрутки появится автоматически, когда это произойдет, но это не так. я попытался найти свойство полосы прокрутки на панели свойств, но не смог его найти.
Как я могу сделать вертикальную полосу прокрутки, созданные автоматически для моего TextBlock Как только его содержимое превысит его высоту?
уточнение: я бы предпочел сделать это от дизайнера, а не напрямую запись в XAML.
8 ответов:
оберните его в Средство просмотра прокрутки:
<ScrollViewer> <TextBlock /> </ScrollViewer>Примечание этот ответ относится к
TextBlock(текстовый элемент только для чтения), как указано в исходном вопросе.если вы хотите показать полосы прокрутки в элементе
TextBox(редактируемый текстовый элемент) затем используйтеScrollViewerсвойства:<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />допустимые значения для этих двух свойств
Disabled,Auto,HiddenиVisible.
теперь можно использовать следующее:
<TextBox Name="myTextBox" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">SOME TEXT </TextBox>
что-то лучше будет:
<Grid Width="Your-specified-value" > <ScrollViewer> <TextBlock Width="Auto" TextWrapping="Wrap" /> </ScrollViewer> </Grid>это гарантирует, что текст в вашем текстовом блоке не переполняется и не перекрывает элементы под текстовым блоком, как это может быть в случае, если вы не используете сетку. Это произошло со мной, когда я попробовал другие решения, хотя текстовый блок уже был в сетке с другими элементами. Имейте в виду, что ширина текстового блока должна быть автоматической, и вы должны указать желаемый С в элементе сетки. Я сделал это в своем коде, и это работает красиво. ХТ.
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto"> <TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" /> </ScrollViewer>Это способ использовать текстовое поле прокрутки в XAML и использовать его в качестве текстовой области.
этот ответ описывает решение с использованием 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 переключает вложенные свойства для управления текстовым полем.
- как это с помощью "добавить", это молниеносно.
- любой другой ViewModel может генерировать сообщения журнала путем вызова методов на модель представления лесозаготовки.
- как мы используем ScrollViewer встроенный в текстовое поле, мы можем сделать его автоматически прокручивать в нижней части текстового поля каждый раз, когда новое сообщение добавляется.
<ScrollViewer MaxHeight="50" Width="Auto" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <TextBlock Text="{Binding Path=}" Style="{StaticResource TextStyle_Data}" TextWrapping="Wrap" /> </ScrollViewer>Я делаю это по-другому, помещая MaxHeight в ScrollViewer.
просто отрегулируйте MaxHeight, чтобы показать больше или меньше строк текста. Простой.
можно использовать
ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible"это присоединенное свойство wpf. Для получения дополнительной информации
http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html
Не знаю, если кто-то еще имеет эту проблему, но обертывание мой
TextBlockнаScrollViewersomewhow испортил мой пользовательский интерфейс - как простой обходной путь я понял, что заменаTextBlockнаTextBoxкак это<TextBox Name="textBlock" SelectionBrush="Transparent" Cursor="Arrow" IsReadOnly="True" Text="My Text" VerticalScrollBarVisibility="Auto">создает
TextBoxчто выглядит и ведет себя какTextBlockС помощью полосы прокрутки (и вы можете сделать все это в конструкторе).
Comments