我正在使用MVVM模式,我有一个创建新ViewModel
的视图,在用户单击“保存”后,此视图将关闭,并打开一个单独的视图,其中显示{的一组视图模型{1}}。
此ListView
按字母顺序排序,因此新的ListView
可能会显示在ViewModel
的底部,而用户无法立即看到它。
我的问题是如何让视图自动滚动到新添加的项目?
我想它将使用附加行为和ListBox
上的ScrollIntoView
事件,但是我需要从ListView
捕获的哪个事件我不确定..
干杯
答案 0 :(得分:15)
答案 1 :(得分:3)
使用ListBox
的另一种解决方案。要实现自动滚动,您可以创建自定义控件!
<小时/>
public class LoggingListBox : ListBox
{
///<summary>
///Define the AutoScroll property. If enabled, causes the ListBox to scroll to
///the last item whenever a new item is added.
///</summary>
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.Register(
"AutoScroll",
typeof(Boolean),
typeof(LoggingListBox),
new FrameworkPropertyMetadata(
true, //Default value.
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
AutoScroll_PropertyChanged));
/// <summary>
/// Gets or sets whether or not the list should scroll to the last item
/// when a new item is added.
/// </summary>
[Category("Common")] //Indicate where the property is located in VS designer.
public bool AutoScroll
{
get { return (bool)GetValue(AutoScrollProperty); }
set { SetValue(AutoScrollProperty, value); }
}
/// <summary>
/// Event handler for when the AutoScroll property is changed.
/// This delegates the call to SubscribeToAutoScroll_ItemsCollectionChanged().
/// </summary>
/// <param name="d">The DependencyObject whose property was changed.</param>
/// <param name="e">Change event args.</param>
private static void AutoScroll_PropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SubscribeToAutoScroll_ItemsCollectionChanged(
(LoggingListBox)d,
(bool)e.NewValue);
}
/// <summary>
/// Subscribes to the list items' collection changed event if AutoScroll is enabled.
/// Otherwise, it unsubscribes from that event.
/// For this to work, the underlying list must implement INotifyCollectionChanged.
///
/// (This function was only creative for brevity)
/// </summary>
/// <param name="listBox">The list box containing the items collection.</param>
/// <param name="subscribe">Subscribe to the collection changed event?</param>
private static void SubscribeToAutoScroll_ItemsCollectionChanged(
LoggingListBox listBox, bool subscribe)
{
INotifyCollectionChanged notifyCollection =
listBox.Items.SourceCollection as INotifyCollectionChanged;
if (notifyCollection != null)
{
if (subscribe)
{
//AutoScroll is turned on, subscribe to collection changed events.
notifyCollection.CollectionChanged +=
listBox.AutoScroll_ItemsCollectionChanged;
}
else
{
//AutoScroll is turned off, unsubscribe from collection changed events.
notifyCollection.CollectionChanged -=
listBox.AutoScroll_ItemsCollectionChanged;
}
}
}
/// <summary>
/// Event handler called only when the ItemCollection changes
/// and if AutoScroll is enabled.
/// </summary>
/// <param name="sender">The ItemCollection.</param>
/// <param name="e">Change event args.</param>
private void AutoScroll_ItemsCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
int count = Items.Count;
ScrollIntoView(Items[count - 1]);
}
}
/// <summary>
/// Constructor a new LoggingListBox.
/// </summary>
public LoggingListBox()
{
//Subscribe to the AutoScroll property's items collection
//changed handler by default if AutoScroll is enabled by default.
SubscribeToAutoScroll_ItemsCollectionChanged(
this, (bool)AutoScrollProperty.DefaultMetadata.DefaultValue);
}
}
以下是在XAML中使用控件的方法:
<tools:LoggingListBox/> <!-- AutoScroll="true" by default. -->
您需要在某处指定访问此控件的方式。这完全取决于您的项目设置。
xmlns:tools="clr-namespace:MyCustomControls;assembly=MyCustomControls"
要创建自定义控件,您只需要C#代码。我们通过扩展ListBox
并仅添加一个属性 AutoScroll 来实现此目的。因为它是一个依赖属性,它将参与WPF绑定系统,这也使它在Visual Studio设计器中可用。
覆盖依赖属性是一个相当大的主题,但是创建自定义控件是不可或缺的。您可以在Control Authoring Overview或Dependency Properties Overview上了解详情。
目标是订阅基础项目集合的集合更改事件,以便我们可以在添加新项目时通过滚动到底部进行响应。我们必须在两个地方订阅这个活动。
AutoScroll
设置为 true 时,我们都需要订阅。 AutoScroll
的价值可能随时发生变化,我们应该能够做出相应的回应。如果设置为 false ,我们应该通过取消订阅来指示控件停止滚动到底部。AutoScroll
只需要在编译时设置,我们需要一种在启动时订阅的方法。这是通过使用控件的构造函数完成的。首先,我们尽可能简化了XAML。我们只需要访问控件并可选择指定或绑定到AutoScroll
属性。
符合MVVM标准。我们的视图模型不需要担心AutoScroll
功能,因为它在控件中是自包含的。同时,视图模型可以提供AutoScroll
属性所绑定的属性,从而为我们提供所需的视图和视图的解耦。图的模型。
此外,我们避免使用行为。这意味着我们已从项目中删除了两个依赖项(授予这是这些依赖项首先包含在内的唯一原因)。我们可以安全地从项目引用中省略 System.Windows.Interactivity 和 Microsoft.Expressions.Interactions 。
这种方法只有一个缺点。基础项集合必须实现INotifyCollectionChanged
。在大多数情况下,这不是问题。如果您正在使用MVVM,那么您可能已经将项目包含在ObservableCollection
内,该{
"windows":
{
"cmd": ["g++", "$file_name","-o", "${file_base_name}.exe", "-lm", "-Wall", "&", "start", "${file_base_name}.exe"]
},
"selector": "source.c++",
"shell": true,
"working_dir": "${file_path}"
}
已经实现了我们所需的接口。
享受! : - )
答案 2 :(得分:2)
将所选项DependecyProperty添加到包含该集合的类中。将listview的SelectedItem绑定到它。将新模型添加到集合后,设置所选项目DependencyProperty。
答案 3 :(得分:-2)
这可能不适用于WPF,但在WinForms中,代码类似于lstData.EnsureVisible(itemIndex);
答案 4 :(得分:-2)
嗯谈论矫枉过正,对于一个更简单的方法和我想象中最常用的方法......
对于listview来说只是打击:
listView1.EnsureVisible(listView1.Items.Count - 1);
对于Listbox而言,只需查看:
listBox1.SelectedIndex = listBox1.Items.Count - 1;
listBox1.SelectedIndex = -1;
到列表视图项目添加(..etc)方法... ..或者在计时器上打它。
OP下面的方式对我来说似乎有很大帮助我很懒... 所有代码都解释了自己。