ListBox使用MVVM滚动到视图中

我有一个非常简单的问题,但我无法弄清楚如何使用MVVM破解它。

我有一个绑定到ObservableCollectionListBox

我运行一个进程,将一大堆项添加到集合中,因此它们显示在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]); } } }