将ListView的SelectedItem绑定到ViewModel

我有一个列表视图,在viewmodel中绑定项目与属性。

                 

并在viewmodel中。

 ICollectionView _businessCollection public ICollectionView BusinessCollection { get { return _businessCollection; } set { _businessCollection = value; RaisePropertyOnChange("BusinessCollection"); } } 

如何在viewmodel中获取businesscollection的选定项?

1.源绑定的一种方法:

您必须使用SelectionChanged事件。 最简单的方法是在codebehind中编写eventhandler以将“binditems”绑定到viewmodel。

 //ViewModel public ICollectionView BusinessCollection {get; set;} public List SelectedObject {get; set;} //Codebehind private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { var viewmodel = (ViewModel) DataContext; viewmodel.SelectedItems = listview.SelectedItems .Cast() .ToList(); } 

这仍然与MVVM设计保持一致,因为视图和视图模型的可靠性保持分离。 您在代码隐藏中没有任何逻辑,并且viewmodel是干净且可测试的。

2.双向绑定:

如果您还需要更新视图,则当viewmodel更改时,您必须附加到ViewModel的PropertyChanged事件和所选项的CollectionChanged事件。 当然你可以在代码隐藏中做到这一点,但在这种情况下我会创建一些更可重用的东西:

 //ViewModel public ObservableCollection SelectedObject {get; set;} //in codebehind: var binder = new SelectedItemsBinder(listview, viewmodel.SelectedItems); binder.Bind(); 

或者可以创建自定义附加属性,因此您可以在xaml中使用绑定语法:

  
 public class SelectedItemsBinder { private ListView _listView; private IList _collection; public SelectedItemsBinder(ListView listView, IList collection) { _listView = listView; _collection = collection; _listView.SelectedItems.Clear(); foreach (var item in _collection) { _listView.SelectedItems.Add(item); } } public void Bind() { _listView.SelectionChanged += ListView_SelectionChanged; if (_collection is INotifyCollectionChanged) { var observable = (INotifyCollectionChanged) _collection; observable.CollectionChanged += Collection_CollectionChanged; } } public void UnBind() { if (_listView != null) _listView.SelectionChanged -= ListView_SelectionChanged; if (_collection != null && _collection is INotifyCollectionChanged) { var observable = (INotifyCollectionChanged) _collection; observable.CollectionChanged -= Collection_CollectionChanged; } } private void Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { foreach (var item in e.NewItems ?? new object[0]) { if (!_listView.SelectedItems.Contains(item)) _listView.SelectedItems.Add(item); } foreach (var item in e.OldItems ?? new object[0]) { _listView.SelectedItems.Remove(item); } } private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { foreach (var item in e.AddedItems ?? new object[0]) { if (!_collection.Contains(item)) _collection.Add(item); } foreach (var item in e.RemovedItems ?? new object[0]) { _collection.Remove(item); } } } 

附属物实施

 public class ListViewExtensions { private static SelectedItemsBinder GetSelectedValueBinder(DependencyObject obj) { return (SelectedItemsBinder)obj.GetValue(SelectedValueBinderProperty); } private static void SetSelectedValueBinder(DependencyObject obj, SelectedItemsBinder items) { obj.SetValue(SelectedValueBinderProperty, items); } private static readonly DependencyProperty SelectedValueBinderProperty = DependencyProperty.RegisterAttached("SelectedValueBinder", typeof(SelectedItemsBinder), typeof(ListViewExtensions)); public static readonly DependencyProperty SelectedValuesProperty = DependencyProperty.RegisterAttached("SelectedValues", typeof(IList), typeof(ListViewExtensions), new FrameworkPropertyMetadata(null, OnSelectedValuesChanged)); private static void OnSelectedValuesChanged(DependencyObject o, DependencyPropertyChangedEventArgs value) { var oldBinder = GetSelectedValueBinder(o); if (oldBinder != null) oldBinder.UnBind(); SetSelectedValueBinder(o, new SelectedItemsBinder((ListView)o, (IList)value.NewValue)); GetSelectedValueBinder(o).Bind(); } public static void SetSelectedValues(Selector elementName, IEnumerable value) { elementName.SetValue(SelectedValuesProperty, value); } public static IEnumerable GetSelectedValues(Selector elementName) { return (IEnumerable)elementName.GetValue(SelectedValuesProperty); } } 

由于itemSource是BusinessCollection,您应该能够:

 var selectedItems = BusinessCollection.Where(x => x.IsSelected); 

将其作为VM上的属性包装。 希望能帮助到你!