ListBox使用MVVM滚动到视图中
我有一个非常简单的问题,但我无法弄清楚如何使用MVVM破解它。
我有一个绑定到ObservableCollection
的ListBox
。
我运行一个进程,将一大堆项添加到集合中,因此它们显示在ListBox
。
问题是,当项目被添加到列表框…滚动条刚刚增长,但我似乎无法弄清楚如何使其添加到集合中的每个项目ScrollIntoView
。
此示例代码完美地说明了该问题。
XAML
查看模型
namespace Stack { using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows.Input; using GalaSoft.MvvmLight.Command; /// /// TODO: Update summary. /// public class MainWindowViewModel : INotifyPropertyChanged { private readonly BackgroundWorker _worker; private ICommand _commandName; private ObservableCollection _myValue = new ObservableCollection(); /// /// Initializes a new instance of the class. /// public MainWindowViewModel() { this._worker = new BackgroundWorker(); this._worker.DoWork += new DoWorkEventHandler(DoWork); this._worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged); this._worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) { CommandManager.InvalidateRequerySuggested(); }; } /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; public ICommand CommandName { get { if (this._commandName == null) { this._commandName = new RelayCommand(() => this.CommandMethod()); } return this._commandName; } } /// /// Gets or sets my value. /// /// My value. public ObservableCollection MyValue { get { return this._myValue; } set { this._myValue = value; this.NotifyPropertyChange("MyValue"); } } /// /// Notifies the property change. /// /// Name of the prop. internal void NotifyPropertyChange(string propName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } /// /// Commands the method. /// private void CommandMethod() { this.MyValue.Clear(); this._worker.RunWorkerAsync(); this._worker.WorkerReportsProgress = true; } /// /// Does the work. /// /// The sender. /// The instance containing the event data. private void DoWork(object sender, DoWorkEventArgs e) { this.Populate(); } /// /// Populates this instance. /// private void Populate() { for (int index = 0; index < 100; index++) { System.Threading.Thread.Sleep(10); this._worker.ReportProgress(index); } } /// /// Progresses the changed. /// /// The sender. /// The instance containing the event data. private void ProgressChanged(object sender, ProgressChangedEventArgs e) { this.MyValue.Add(e.ProgressPercentage.ToString()); } }
}
您可以创建DependencyProperty
或只是扩展ListBox
控件并使用您的新控件。
public class ScrollingListBox : ListBox { protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { int newItemCount = e.NewItems.Count; if(newItemCount > 0) this.ScrollIntoView(e.NewItems[newItemCount - 1]); base.OnItemsChanged(e); } }
在您的XAML中,添加类的命名空间:
xmlns:custom="clr-namespace:ScrollingListBoxNamespace"
并将您的标准ListBox
替换为您的自定义ListBox
:
您还可以添加行为:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" . . .
并实现行为:
using System.Windows.Interactivity; public class ScrollIntoViewBehavior : Behavior { protected override void OnAttached() { ListBox listBox = AssociatedObject; ((INotifyCollectionChanged)listBox.Items).CollectionChanged += OnListBox_CollectionChanged; } protected override void OnDetaching() { ListBox listBox = AssociatedObject; ((INotifyCollectionChanged)listBox.Items).CollectionChanged -= OnListBox_CollectionChanged; } private void OnListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { ListBox listBox = AssociatedObject; if (e.Action == NotifyCollectionChangedAction.Add) { // scroll the new item into view listBox.ScrollIntoView(e.NewItems[0]); } } }