我在WPF中有一个 TextBlock . 我写了很多行,远远超过它的垂直高度 . 我预计一个垂直滚动条会在发生时自动出现,但事实并非如此 . 我试图在“属性”窗格中查找滚动条属性,但找不到 .
TextBlock
一旦内容超出其高度,如何为我的 TextBlock 自动创建垂直滚动条?
澄清:我宁愿从设计师那里做,而不是直接写给XAML .
将它包装在滚动查看器中:
<ScrollViewer> <TextBlock /> </ScrollViewer>
NOTE 此答案适用于原始问题中要求的 TextBlock (只读文本元素) .
如果要在 TextBox (可编辑的文本元素)中显示滚动条,请使用 ScrollViewer 附加属性:
TextBox
ScrollViewer
<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
这两个属性的有效值为 Disabled , Auto , Hidden 和 Visible .
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>
这样可以确保文本块中的文本不会溢出并重叠文本块下面的元素,如果不使用网格则可能会出现这种情况 . 当我尝试其他解决方案时,即使文本块已经在其他元素的网格中,这也发生在我身上 . 请记住,文本块的宽度应为“自动”,您应在Grid元素中指定所需的宽度 . 我在我的代码中做到了这一点,它的工作非常精彩 . HTH .
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto"> <TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" /> </ScrollViewer>
这是在XAML中使用滚动TextBox并将其用作文本区域的方法 .
这个答案描述了使用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时,我们可以在每次添加新消息时自动滚动到文本框的底部 .
<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
我试图将这些建议用于文本块,但无法使其工作 . 我甚至试图从设计师那里得到它 . (查看布局并通过单击底部的向下箭头"V"展开列表)我尝试将scrollviewer设置为 Visible 然后 Auto ,但它仍然无效 .
我最终放弃了并将 TextBlock 更改为 TextBox 并设置了 Readonly 属性,它就像一个魅力 .
不知道是否有其他人有这个问题,但将我的 TextBlock 包装成 ScrollViewer 某些人搞砸了我的用户界面 - 作为一个简单的解决方法我发现用 TextBox 替换 TextBlock 就像这个
<TextBox Name="textBlock" SelectionBrush="Transparent" Cursor="Arrow" IsReadOnly="True" Text="My Text" VerticalScrollBarVisibility="Auto">
创建一个 TextBox ,其外观和行为类似于带有滚动条的 TextBlock (您可以在设计器中完成所有操作) .
这是该问题的简单解决方案 . 仅当文本溢出时才会激活垂直滚动 .
<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />
10 回答
将它包装在滚动查看器中:
NOTE 此答案适用于原始问题中要求的
TextBlock
(只读文本元素) .如果要在
TextBox
(可编辑的文本元素)中显示滚动条,请使用ScrollViewer
附加属性:这两个属性的有效值为
Disabled
,Auto
,Hidden
和Visible
.现在可以使用以下内容:
更好的是:
这样可以确保文本块中的文本不会溢出并重叠文本块下面的元素,如果不使用网格则可能会出现这种情况 . 当我尝试其他解决方案时,即使文本块已经在其他元素的网格中,这也发生在我身上 . 请记住,文本块的宽度应为“自动”,您应在Grid元素中指定所需的宽度 . 我在我的代码中做到了这一点,它的工作非常精彩 . HTH .
这是在XAML中使用滚动TextBox并将其用作文本区域的方法 .
这个答案描述了使用MVVM的解决方案 .
如果要向窗口添加日志框,则此解决方案非常有用,每次添加新的日志消息时,该窗口都会自动滚动到底部 .
一旦添加了这些附加属性,它们就可以在任何地方重复使用,因此它可以生成非常模块化和可重用的软件 .
添加此XAML:
添加此附加属性:
这个附加属性(清除框):
然后,如果您正在使用依赖注入框架(如MEF),则可以将所有特定于日志记录的代码放入其自己的ViewModel中:
以下是它的工作原理:
ViewModel切换附加属性以控制TextBox .
因为它闪电般快速 .
任何其他ViewModel都可以通过调用日志记录ViewModel上的方法来生成日志记录消息 .
当我们使用TextBox中内置的ScrollViewer时,我们可以在每次添加新消息时自动滚动到文本框的底部 .
我通过将MaxHeight放在ScrollViewer中以另一种方式执行此操作 .
只需调整MaxHeight即可显示更多或更少的文本行 . 简单 .
您可以使用
这些是wpf的附加属性 . 欲获得更多信息
http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html
我试图将这些建议用于文本块,但无法使其工作 . 我甚至试图从设计师那里得到它 . (查看布局并通过单击底部的向下箭头"V"展开列表)我尝试将scrollviewer设置为 Visible 然后 Auto ,但它仍然无效 .
我最终放弃了并将
TextBlock
更改为TextBox
并设置了 Readonly 属性,它就像一个魅力 .不知道是否有其他人有这个问题,但将我的
TextBlock
包装成ScrollViewer
某些人搞砸了我的用户界面 - 作为一个简单的解决方法我发现用TextBox
替换TextBlock
就像这个创建一个
TextBox
,其外观和行为类似于带有滚动条的TextBlock
(您可以在设计器中完成所有操作) .这是该问题的简单解决方案 . 仅当文本溢出时才会激活垂直滚动 .
<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />