【问题标题】:Scrolling a ScrollViewer to the bottom in WPF when a new line is added to a TextBlock in XAML当新行添加到 XAML 中的 TextBlock 时,将 ScrollViewer 滚动到 WPF 中的底部
【发布时间】:2019-11-13 15:32:02
【问题描述】:

我试图将垂直滚动条保持在底部(最新条目),但此刻,滚动条只是停留在同一个地方,所以当内容被添加到字符串中时,滚动条移动到顶部。

我知道我可以在我的代码隐藏中使用ServerScroll.ScrollToEnd() 属性将条形移到末尾。但是有没有办法自动做到这一点是xaml? (这样我就不必每次添加到字符串时都调用此属性)。

XAML

<ScrollViewer Name="ServerScroll"
              VerticalScrollBarVisibility="Auto">
    <TextBlock Name="serverConsole"
               Margin="5"
               Background="White"
               TextWrapping="Wrap"/>
</ScrollViewer>

代码隐藏

private void example_Click(object sender, RoutedEventArgs e)
{
    ServerConsole += "asdf\r\n";      // binded to TextBlock
    ServerScroll.ScrollToEnd();    
}

【问题讨论】:

  • 你到底想在什么条件下滚动到最后?每次ScrollViewer的内容都变了?每次TextBlockText 发生变化?我认为您在代码隐藏中的解决方案非常清晰明了,顺便说一句,我怀疑在 XAML 中这样做会很棘手而且不太清楚。
  • @CorentinPane 每次在绑定到TextBlock 的字符串中添加一个新行,以便随时可以看到最新条目。我只是认为在每个新条目之后添加 .ScrollToEnd() 是多余的,并且想知道是否有更短的方法,也许在 xaml 属性中。我猜不是?

标签: c# wpf scrollviewer eventtrigger


【解决方案1】:

使用文本框,对TextBox.TextChanged做出反应

如果您想在每次更改 TextBlockText 属性时滚动到末尾,我建议切换到 TextBox 以便您可以使用 TextChanged 连接到其 TextChanged 事件@:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Width="50" Height="25" Click="Button_Click"></Button>
        <ScrollViewer Grid.Row="1" Name="ServerScroll"
                      VerticalScrollBarVisibility="Auto">
            <TextBox Name="serverConsole"
                       Margin="5"
                       Background="White"
                       TextWrapping="Wrap">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged">
                        <ei:CallMethodAction MethodName="ScrollToEnd" TargetObject="{Binding ElementName=ServerScroll}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
        </ScrollViewer>
    </Grid>
</Window>

使用 TextBlock,对Button.Click做出反应

如果您希望在单击 Button 时滚动到末尾,您可以使用相同的技术连接到其 Click 事件:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Width="50" Height="25" Click="Button_Click">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:CallMethodAction MethodName="ScrollToEnd" TargetObject="{Binding ElementName=ServerScroll}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <ScrollViewer Grid.Row="1" Name="ServerScroll"
                      VerticalScrollBarVisibility="Auto">
            <TextBlock Name="serverConsole"
                       Margin="5"
                       Background="White"
                       TextWrapping="Wrap">
            </TextBlock>
        </ScrollViewer>
    </Grid>
</Window>

使用 ListView,对CollectionChanged做出反应

看起来您确实想使用ItemsControl 而不是TextBlock,因为您正在谈论条目和所有内容。您也可以切换到 ListView 并连接到其 CollectionChanged 事件:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Width="50" Height="25" Click="Button_Click"/>

        <ScrollViewer Grid.Row="1" Name="ServerScroll"
                      VerticalScrollBarVisibility="Auto">
            <ListView x:Name="listView" ItemsSource="{Binding MyList}">
                <i:Interaction.Triggers>
                    <i:EventTrigger SourceObject="{Binding MyList}" EventName="CollectionChanged">
                        <ei:CallMethodAction MethodName="ScrollToEnd" TargetObject="{Binding ElementName=ServerScroll}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ListView>
        </ScrollViewer>
    </Grid>
</Window>

在你的视图模型中:

public ObservableCollection<string> MyList { get; } = new ObservableCollection<string>();

【讨论】:

  • 感谢您提供清晰的示例!我认为这会做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-23
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多