【问题标题】:WPF: auto scroll VlistView to last itemWPF:自动滚动 VlistView 到最后一项
【发布时间】:2021-01-18 16:29:10
【问题描述】:

所以在我的应用程序中,我打开了特定进程,读取它的输出并将其放入我的ListView

<ListView Name="listViewResults"
          ItemsSource="{Binding Results}"/>

视图模型

private ObservableCollection<string> results;

过程输出

private void OutputHandler(object sender, DataReceivedEventArgs e)
{
    if (line != null)
    {
        results.Add(line);
    }    
}

所以我创建了另一个property

private string currentLog;
public string CurrentLog
{
    get { return currentLog; }
    set
    {
        currentLog = value;
        NotifyPropertyChanged("CurrentLog");
    }
}

并将其添加到我的 OutputHandler method:

CurrentLog = line;

并在我的ListView SelectedItem property 在我的XAML 中使用它:

<ListView Name="listViewResults"
          ItemsSource="{Binding Results}"
          SelectedItem="{Binding CurrentLog}"/>

结果还是需要手动向下滚动。

【问题讨论】:

标签: wpf listview binding


【解决方案1】:

ListView 中选择一个项目不会自动将其滚动到视图中,并且您不能仅在 XAML 中执行此操作,但有代码隐藏的替代方法。您可以编写自定义行为。行为是可重用的组件,您可以将其附加到 XAML 中的控件。

为此,请将Microsoft.Xaml.Behaviors.Wpf Nuget 包安装到您的项目中。然后像这样创建一个派生自Behavior&lt;ListView&gt; 的类型。

public class ScrollIntoSelectedItemBehavior : Behavior<ListView>
{
   protected override void OnAttached()
   {
      base.OnAttached();
      AssociatedObject.SelectionChanged += OnSelectionChanged;
   }

   protected override void OnDetaching()
   {
      base.OnDetaching();
      AssociatedObject.SelectionChanged -= OnSelectionChanged;
   }

   private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
   {
      var selectedItem = AssociatedObject.SelectedItem;
      if (selectedItem != null)
         AssociatedObject.ScrollIntoView(selectedItem);
   }
}

当行为附加到ListView 控件时,将调用OnAttach 方法。然后它会监听选择的变化并滚动到当前选中的项目(如果有的话)。

关于行为的一个很酷的地方是它们不驻留在您的代码隐藏中,您可以在任何兼容的控件上重用它们。要将行为附加到您的 ListView,请执行此操作。

<ListView Name="listViewResults"
          ItemsSource="{Binding Results}"
          SelectedItem="{Binding CurrentLog}">
   <b:Interaction.Behaviors>
      <local:ScrollIntoSelectedItemBehavior/>
   </b:Interaction.Behaviors>
</ListView>

Interaction 类型的 XML 命名空间添加到您的 XAML 文件中。

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"

就是这样。当您设置不同的CurrentLog 项目时,它将自动滚动到视图中。


我还想指出您设计中的一个潜在问题。您的 Results 集合包含 string 类型的项目。如果存在重复项,您将遇到意外行为。

让第 42 项为 "Test",然后添加也拼写为 "Test" 的第 102 项,列表将滚动到第 42 项,因为两个项目相等并且列表中的第一个获胜。为了解决这个问题,您必须创建一个自定义数据类型作为实际 string 的包装器,例如:

public MyDataItem
{
   public string Log { get; }

   public MyDataItem(string log)
   {
      Log = log;
   }

   // ...
}

这将起作用,因为将比较引用而不是字符串,并且它们是唯一的。

【讨论】:

  • @DanaYeger 究竟是什么不起作用?您的结果项是否已添加并显示在ListView 中? SelectedItem 是否设置为当前添加的项目,例如您看到ListView 中的选择发生了变化吗?您的OutputHandler 方法未显示您将新项目分配给CurrentLog
  • 我可以看到添加到列表中的新项目,但我需要手动滚动,我正在使用此 CurrentLog 并将其绑定到我的 ListView,如我在帖子中显示的那样
  • @DanaYeger 您是否看到当添加项目时,选择更改为新添加的项目在您的ListView 中?
  • 不,我没有看到它,我没有使用任何样式
  • @DanaYeger 这就是我的想法。问题不在于行为,而是您的绑定不起作用,CurrentLog 属性未设置或设置不正确,或者未针对错误属性引发或引发属性更改事件或未正确实现。查找属性名称中的拼写错误。输出窗口是否有绑定错误?
猜你喜欢
  • 2022-07-14
  • 2010-12-21
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多