1. Một cách để nguồn ràng buộc:
Bạn phải sử dụng SelectionChanged
sự kiện. Cách dễ nhất là viết eventhandler trong codebehind thành "bind selecteditems" thành viewmodel.
//ViewModel
public ICollectionView BusinessCollection {get; set;}
public List<YourBusinessItem> SelectedObject {get; set;}
//Codebehind
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var viewmodel = (ViewModel) DataContext;
viewmodel.SelectedItems = listview.SelectedItems
.Cast<YourBusinessItem>()
.ToList();
}
Điều này vẫn phù hợp với thiết kế MVVM vì chế độ xem và độ tương phản viewmodel được giữ riêng biệt. Bạn không có bất kỳ logic trong codebehind và viewmodel là sạch sẽ và testable.
2. Hai cách ràng buộc:
nếu bạn cũng cần phải cập nhật xem, khi có thay đổi viewmodel, bạn phải gắn với sự kiện PropertyChanged
ViewModel và sự kiện CollectionChanged
các mục đã chọn. Dĩ nhiên bạn có thể làm điều đó trong codebehind, nhưng trong trường hợp này tôi sẽ tạo ra một cái gì đó tái sử dụng hơn:
//ViewModel
public ObservableCollection<YourBusinessItem> SelectedObject {get; set;}
//in codebehind:
var binder = new SelectedItemsBinder(listview, viewmodel.SelectedItems);
binder.Bind();
hoặc có thể tạo tài sản tùy chỉnh kèm theo, vì vậy bạn có thể sử dụng cú pháp ràng buộc trong XAML:
<ListView local:ListViewExtensions.SelectedValues="{Binding SelectedItem}" .../>
public class SelectedItemsBinder
{
private ListView _listBox;
private IList _collection;
public SelectedItemsBinder(ListView listBox, IList collection)
{
_listBox = listBox;
_collection = collection;
_listBox.SelectedItems.Clear();
foreach (var item in _collection)
{
_listBox.SelectedItems.Add(item);
}
}
public void Bind()
{
_listBox.SelectionChanged += ListBox_SelectionChanged;
if (_collection is INotifyCollectionChanged)
{
var observable = (INotifyCollectionChanged) _collection;
observable.CollectionChanged += Collection_CollectionChanged;
}
}
public void UnBind()
{
if (_listBox != null)
_listBox.SelectionChanged -= ListBox_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 (!_listBox.SelectedItems.Contains(item))
_listBox.SelectedItems.Add(item);
}
foreach (var item in e.OldItems ?? new object[0])
{
_listBox.SelectedItems.Remove(item);
}
}
private void ListBox_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);
}
}
}
tài sản gắn liền thực hiện
public class ListBoxExtensions
{
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(ListBoxExtensions));
public static readonly DependencyProperty SelectedValuesProperty = DependencyProperty.RegisterAttached("SelectedValues", typeof(IList), typeof(ListBoxExtensions),
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((ListBox)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);
}
}
Cảm ơn rất nhiều, nó đã giúp tôi rất nhiều :) –
Cảm ơn bạn đã viết mã. Bạn cũng nên xử lý đặt lại bộ sưu tập trong phương thức Collection_CollectionChanged. –