仅当拖动到底部时才将垂直滚动条粘贴到底部
Stick vertical scrollbar to bottom only when dragged to bottom
我在 Scrollviewer 中有一个文本框:
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<TextBox IsReadOnly="True" TextWrapping="Wrap" Text="{Binding Messages, Converter={StaticResource TimedStringListToStringConverter}, UpdateSourceTrigger=PropertyChanged}"/>
</ScrollViewer>
我想将垂直滚动条设置为只有在我手动将其拖到底部时才将其设置为底部,否则它不能移动。
想法?
如果您的 TextBox 是 ReadOnly,那么我倾向于使用代码隐藏来调用 ScrollToHome。如果您使用 TextBox 自己的 ScrollViewer,则需要设置一个明确的 Height 以强制显示 ScrollViewer。
XAML
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox x:Name="MyTextBox"
Grid.Row="0"
Width="80"
Height="100"
FontSize="20"
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
TextChanged="MyTextBox_TextChanged"
TextWrapping="Wrap" />
<Button Grid.Row="1"
Width="50"
Height="50"
Click="Button_Click"
Content="OK" />
</Grid>
代码隐藏
private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
MyTextBox.ScrollToHome();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyTextBox.Text += "TEXT ";
}
为了达到你想要的效果(只有当你已经手动向下滚动到最后才滚动到最后)并使用 TextBox 自己的 ScrollViewer,你只需要处理 TextChanged
事件和代码隐藏这样做:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
var max = (textBox.ExtentHeight - textBox.ViewportHeight);
var offset = textBox.VerticalOffset;
if (max != 0 && max == offset)
this.Dispatcher.BeginInvoke(new Action(() =>
{
textBox.ScrollToEnd();
}),
System.Windows.Threading.DispatcherPriority.Loaded);
}
如果您需要在 TextBox 周围使用额外的 ScrollViewer,则只需使用该 ScrollViewer 的 ExtentHeight
、ViewportHeight
和 VerticalOffset
,并调用该 ScrollViewer 的 ScrollToBottom
(而不是 TextBox 的 ScrollToEnd
).
请记住,文本输入插入符号的位置不会改变,因此如果您尝试手动输入文本,滚动将跳转到插入符号所在的位置。
我在 Scrollviewer 中有一个文本框:
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<TextBox IsReadOnly="True" TextWrapping="Wrap" Text="{Binding Messages, Converter={StaticResource TimedStringListToStringConverter}, UpdateSourceTrigger=PropertyChanged}"/>
</ScrollViewer>
我想将垂直滚动条设置为只有在我手动将其拖到底部时才将其设置为底部,否则它不能移动。
想法?
如果您的 TextBox 是 ReadOnly,那么我倾向于使用代码隐藏来调用 ScrollToHome。如果您使用 TextBox 自己的 ScrollViewer,则需要设置一个明确的 Height 以强制显示 ScrollViewer。
XAML
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox x:Name="MyTextBox"
Grid.Row="0"
Width="80"
Height="100"
FontSize="20"
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
TextChanged="MyTextBox_TextChanged"
TextWrapping="Wrap" />
<Button Grid.Row="1"
Width="50"
Height="50"
Click="Button_Click"
Content="OK" />
</Grid>
代码隐藏
private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
MyTextBox.ScrollToHome();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyTextBox.Text += "TEXT ";
}
为了达到你想要的效果(只有当你已经手动向下滚动到最后才滚动到最后)并使用 TextBox 自己的 ScrollViewer,你只需要处理 TextChanged
事件和代码隐藏这样做:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
var max = (textBox.ExtentHeight - textBox.ViewportHeight);
var offset = textBox.VerticalOffset;
if (max != 0 && max == offset)
this.Dispatcher.BeginInvoke(new Action(() =>
{
textBox.ScrollToEnd();
}),
System.Windows.Threading.DispatcherPriority.Loaded);
}
如果您需要在 TextBox 周围使用额外的 ScrollViewer,则只需使用该 ScrollViewer 的 ExtentHeight
、ViewportHeight
和 VerticalOffset
,并调用该 ScrollViewer 的 ScrollToBottom
(而不是 TextBox 的 ScrollToEnd
).
请记住,文本输入插入符号的位置不会改变,因此如果您尝试手动输入文本,滚动将跳转到插入符号所在的位置。