自动垂直滚动条在WPF TextBlock?

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

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

澄清:我宁愿从设计器中完成,而不是直接写入XAML。

296626 次浏览

在滚动查看器中包装它:

<ScrollViewer>
<TextBlock />
</ScrollViewer>

请注意这个答案适用于原问题中要求的TextBlock(只读文本元素)。

如果你想在TextBox(一个可编辑的文本元素)中显示滚动条,那么使用ScrollViewer附加属性:

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

这两个属性的有效值是DisabledAutoHiddenVisible

现在可以使用以下:

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

这确保文本在你的文本块不溢出和重叠的文本块下面的元素,如果你不使用网格可能是这种情况。当我尝试其他解决方案时,即使文本块已经在与其他元素的网格中,这种情况也发生在我身上。请记住,文本块的宽度应该是Auto,你应该在Grid元素中指定所需的宽度。我在我的代码中这样做了,它工作得很漂亮。 HTH . < / p >

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

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

你可以使用

ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
这些是wpf的附加属性。 更多信息

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

这个答案描述了一个使用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上的方法来生成日志消息。
  • 当我们使用内置在文本框中的ScrollViewer时,我们可以使它在每次添加新消息时自动滚动到文本框的底部。
<ScrollViewer MaxHeight="50"
Width="Auto"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="{Binding Path=}"
Style="{StaticResource TextStyle_Data}"
TextWrapping="Wrap" />
</ScrollViewer>

我用另一种方式做到这一点,把MaxHeight放在ScrollViewer中。

只需调整MaxHeight来显示更多或更少的文本行。一件容易的事。

不知道是否有人有这个问题,但包装我的TextBlock到一个ScrollViewer以某种方式混乱了我的UI -作为一个简单的解决办法,我想出了用一个像这样的TextBox替换TextBlock

<TextBox  SelectionBrush="Transparent"
Cursor="Arrow"
IsReadOnly="True"
Text="{Binding Text}"
VerticalScrollBarVisibility="Auto">

创建一个TextBox,它看起来和行为类似于带有滚动条的TextBlock(并且你可以在设计器中完成这一切)。

这是这个问题的一个简单的解决方案。只有当文本溢出时,垂直滚动才会被激活。

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

我试图让这些建议为一个文本块工作,但不能让它工作。我甚至试着让设计师帮我设计。(在布局中查看,并通过单击底部的向下箭头“V”来展开列表)我尝试将滚动查看器设置为可见,然后设置为汽车,但它仍然无法工作。

我最终放弃了,并将TextBlock改为带有< em >只读的< / em >属性集的TextBox,这就像一个魅力。