WPF TextBlock中的自动垂直滚动条?
Posted
技术标签:
【中文标题】WPF TextBlock中的自动垂直滚动条?【英文标题】:Automatic vertical scroll bar in WPF TextBlock? 【发布时间】:2010-11-14 14:35:16 【问题描述】:我在 WPF 中有一个 TextBlock
。我给它写了很多行,远远超过了它的垂直高度。我希望在发生这种情况时会自动出现一个垂直滚动条,但事实并非如此。我试图在“属性”窗格中查找滚动条属性,但找不到。
如果我的TextBlock
的内容超过了它的高度,如何自动创建垂直滚动条?
澄清:我宁愿从设计者那里完成,而不是直接写入 XAML。
【问题讨论】:
重新阅读这个问题后,我注意到您提到了两次TextBlock
和一次TextBox
。
【参考方案1】:
不知道其他人是否有此问题,但将我的 TextBlock
包装到 ScrollViewer
不知何故弄乱了我的 UI - 作为一个简单的解决方法,我发现用 TextBox
替换 TextBlock
就像这样
<TextBox SelectionBrush="Transparent"
Cursor="Arrow"
IsReadOnly="True"
Text="Binding Text"
VerticalScrollBarVisibility="Auto">
创建一个TextBox
,其外观和行为类似于带有滚动条的TextBlock
(您可以在设计器中完成所有操作)。
【讨论】:
【参考方案2】:我试图让这些建议适用于文本块,但无法让它发挥作用。我什至试图让它从设计师那里工作。 (查看布局并通过单击底部的向下箭头“V”来展开列表)我尝试将滚动查看器设置为 Visible,然后设置为 Auto,但它仍然不会不行。
我最终放弃了,将 TextBlock
更改为带有 Readonly 属性集的 TextBox
,它就像一个魅力。
【讨论】:
【参考方案3】:这是该问题的简单解决方案。只有在文本溢出时才会激活垂直滚动。
<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />
【讨论】:
【参考方案4】:<ScrollViewer MaxHeight="50"
Width="Auto"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="Binding Path="
Style="StaticResource TextStyle_Data"
TextWrapping="Wrap" />
</ScrollViewer>
我通过将 MaxHeight 放入 ScrollViewer 以另一种方式做到这一点。
只需调整 MaxHeight 以显示更多或更少的文本行。很简单。
【讨论】:
【参考方案5】:<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" />
</ScrollViewer>
这是在 XAML 中使用滚动文本框并将其用作文本区域的方法。
【讨论】:
该问题与TextBlock
不是TextBox
有关。
不是很正确的答案,但我发现 VerticalScrollBarVisibility 是一个有用的提示,所以 +1【参考方案6】:
此答案描述了使用 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 都可以通过调用日志 ViewModel 上的方法来生成日志消息。 当我们使用 TextBox 中内置的 ScrollViewer 时,我们可以让它在每次添加新消息时自动滚动到文本框的底部。【讨论】:
【参考方案7】:你可以使用
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
这些是 wpf 的附加属性。 欲了解更多信息
http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html
【讨论】:
【参考方案8】:更好的是:
<Grid Width="Your-specified-value" >
<ScrollViewer>
<TextBlock Width="Auto" TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
这可以确保文本块中的文本不会溢出并与文本块下方的元素重叠,如果您不使用网格,可能会出现这种情况。当我尝试其他解决方案时,即使文本块已经在与其他元素的网格中,这种情况也发生在我身上。请记住,文本块的宽度应该是 Auto 并且您应该在 Grid 元素中指定所需的宽度。我在我的代码中做到了这一点,它工作得很好。 HTH。
【讨论】:
【参考方案9】:现在可以使用以下内容:
<TextBox Name="myTextBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True">SOME TEXT
</TextBox>
【讨论】:
@jjnguy,我将原始问题解释为关于TextBlock
而不是TextBox
(如标题和开头行),但第二段提到了TextBox
。需要明确的是,这个答案绝对是文本 boxes 的最佳方法,而我的答案是我所知道的文本 blocks 的最佳方法 :)
@Drew,啊,有道理。感谢您的澄清。
对我来说也更好。至少对于一个 TextBox,当在它周围使用 ScrollViewer 时,就像在接受的答案中一样,TextBox 的边框会消失,因为整个控件都会滚动,而不仅仅是它的内容。【参考方案10】:
将其包装在滚动查看器中:
<ScrollViewer>
<TextBlock />
</ScrollViewer>
注意此答案适用于原始问题中要求的TextBlock
(只读文本元素)。
如果您想在 TextBox
(可编辑的文本元素)中显示滚动条,请使用 ScrollViewer
附加属性:
<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
这两个属性的有效值为Disabled
、Auto
、Hidden
和Visible
。
【讨论】:
设计师怎么做? 对不起,我不确定,我不使用 WPF 设计器。我认为如果您直接添加 XAML,设计器会自行更新。 @conqenator TextBox.ScrollToEnd(); @Greg,问题是关于TextBlock
而不是TextBox
。
如果封闭元素不强制任何高度,有时需要在 Scrollviewer 上设置 MaxHeight 来强制显示 scoll。以上是关于WPF TextBlock中的自动垂直滚动条?的主要内容,如果未能解决你的问题,请参考以下文章