【问题标题】:WPF FlowDocumentScrollViewer automatically scroll to bottom of the documentWPF FlowDocumentScrollViewer 自动滚动到文档底部
【发布时间】:2021-07-25 23:22:00
【问题描述】:

我有一个 XAML 看起来像的 UserControl:

<Grid>
    <FlowDocumentScrollViewer Name="ProvisionStatusMonitor" Document="{Binding Document}" SourceUpdated="OnSourceUpdated"/>
</Grid>

代码隐藏看起来像

    private void OnSourceUpdated(object sender, DataTransferEventArgs e)
    {
        FlowDocumentScrollViewer docViewer = (FlowDocumentScrollViewer) sender;

        var scrollViewer = (ScrollViewer)docViewer.Template
            .FindName("ProvisionStatusMonitor", docViewer);

        scrollViewer.ScrollToEnd();
    }

但这似乎不起作用。当文档更改时,我认为应该触发此事件,并且我可以自动滚动到文档底部。我错过了什么?

【问题讨论】:

  • "ProvisionStatusMonitor" 是错误的。它必须是"PART_ContentHost"。它是 FlowDocumentScrollViewer 可视化树中的一个组件。
  • 是什么让您认为SourceUpdated 会被调用? Binding 源永远不会改变。
  • @Clemens 我正在查看与 FlowDocumentScrollViewer 相关的可能事件,而 SourceUpdated 是我想出的最接近的事件。那么 XAML 应该是什么样子呢?我需要在 XAML 上放一些东西来表明有一些代码隐藏要被调用。
  • 您可以附加 XAML 中答案中显示的 DataContextChanged 事件,而不是 StatusView 构造函数。

标签: c# wpf .net-core


【解决方案1】:

您可以在视图中的 DataContextChanged 处理程序中将 PropertyChanged 事件处理程序附加到视图模型。

假设StatusView 是一个包含问题中显示的 FlowDocumentScrollViewer 的 UserControl,它可能如下所示:

public StatusView()
{
    InitializeComponent();

    DataContextChanged += StatusViewDataContextChanged;
}

private void StatusViewDataContextChanged(
    object sender, DependencyPropertyChangedEventArgs e)
{
    if (e.OldValue is INotifyPropertyChanged oldViewModel)
    {
        oldViewModel.PropertyChanged -= ViewModelPropertyChanged;
    }

    if (e.NewValue is INotifyPropertyChanged newViewModel)
    {
        newViewModel.PropertyChanged += ViewModelPropertyChanged;
    }
}

private void ViewModelPropertyChanged(
    object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Document")
    {
        var docViewer = ProvisionStatusMonitor;

        var scrollViewer = (ScrollViewer)docViewer.Template
            .FindName("PART_ContentHost", docViewer);

        scrollViewer.ScrollToEnd();
    }
}

【讨论】:

  • 我显然有一个 PropertyChanged 通知,该通知会在文档更新时引发。由于我已经有了这个设置(正如您在 DataContext 中指出的那样),我如何确保在视图中处理视图模型中引发的通知? viewModel.PropertyChanged += ViewModelPropertyChanged; 去哪里处理它?在我的情况下,视图模型被分配给视图,因为 &lt;DataTemplate DataType="{x:Type views:StatusViewModel}"&gt; &lt;views:StatusView/&gt; &lt;/DataTemplate&gt; PropertyChanged 之类的资源不存在。
  • 所以这表明我提出了一个文档已更改的事件(这已经完成)。由于视图模型是 DataContext 我基本上会在构造函数 this.PropertyChanged += ViewModelPropertyChanged 中执行此操作
  • 另一个问题。这不是在本质上污染视图模型吗?由于要解决对 FlowDocumentScrollViewer 的引用,我需要引入 System.Windows?
  • 您当然(仍然)不会在视图模型中执行此操作。正如在对您之前的一个问题的评论中所说,滚动是在视图中完成的。 PropertyChanged 事件处理程序可以附加到 StatusView 中的 DataContextChanged 事件处理程序中 - 假设 StatusView 是包含 FlowDocumentScrollViewer 的元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 2017-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多