因此,在我的应用程序中,我打开特定的进程,读取其输出并将其放入我的ListView
:中
<ListView Name="listViewResults"
ItemsSource="{Binding Results}"/>
ViewModel
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");
}
}
并将其添加到我的OutputHandlermethod
:中
CurrentLog = line;
并在我的XAML
:中的ListView
SelectedItemproperty
中使用它
<ListView Name="listViewResults"
ItemsSource="{Binding Results}"
SelectedItem="{Binding CurrentLog}"/>
结果是,我仍然需要手动向下滚动。
在ListView
中选择一个项不会自动将其滚动到视图中,而且您不能仅在XAML中这样做,但有一种替代代码隐藏的方法。您可以编写自定义行为。行为是可以附加到XAML中的控件的可重定位组件。
为此,请安装Microsoft。Xaml。行为。WpfNuget包到您的项目中。然后创建一个从Behavior<ListView>
派生的类型,如下所示。
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;
}
// ...
}
这将起作用,因为将比较引用而不是字符串,并且它们是唯一的。