WPF TextBlock中的自动垂直滚动条?

我在WPF中有一个TextBlock 。 我写了很多行,远远超过了它的垂直高度。 我期望一个垂直滚动条自动出现,但事实并非如此。 我试图在“属性”窗格中查找滚动条属性,但找不到一个属性。

一旦其内容超过其高度,我怎样才能使自动为我的TextBlock创build垂直滚动条?

澄清:我宁愿从devise师那里做,而不是直接写给XAML。

用卷轴查看器包装它:

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

这可以确保文本块中的文本不会溢出,并且可能会覆盖文本块下方的元素(如果不使用网格)。 当我尝试其他解决scheme时,发生在我身上,即使textblock已经与其他元素的网格。 请记住,文本块的宽度应为“自动”,并且应该在“网格”元素中指定所需的值。 我在我的代码中做到了这一点,它的作品非常漂亮。 HTH。

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

这是在XAML中使用滚动的TextBox并将其用作文本区域的方法。

您可以使用

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

这些是wpf的附加属性。 了解更多信息

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

这个答案描述了使用MVVM的解决scheme。

如果你想添加一个日志框到一个窗口,这个解决scheme是非常棒的,每当添加一个新的日志消息时它会自动滚动到底部。

一旦添加了这些附加属性,它们就可以在任何地方重复使用,因此它使得模块化和可重用的软件成为可能。

添加这个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等dependency injection框架,则可以将所有特定于日志logging的代码放入其自己的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都可以通过调用日志ViewModel上的方法来生成日志消息。
  • 当我们使用内置到TextBox中的ScrollViewer时,每次添加新消息时,我们都可以自动滚动到文本框的底部。
 <ScrollViewer MaxHeight="50" Width="Auto" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <TextBlock Text="{Binding Path=}" Style="{StaticResource TextStyle_Data}" TextWrapping="Wrap" /> </ScrollViewer> 

我以另一种方式将MaxHeight放在ScrollViewer中。

只需调整MaxHeight以显示更多或更less的文本行。 简单。