1. Un modo per vincolante fonte:
è necessario utilizzare SelectionChanged
evento. Il modo più semplice è scrivere eventhandler in codebehind per "associare selecteditems" a 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();
}
Ciò allinea ancora con disegno MVVM, perché vista e ViewModel resposibilities sono mantenuti separati. Non hai alcuna logica in codebehind e viewmodel è pulito e testabile.
2. Due modo vincolante:
se anche è necessario aggiornare vista, quando i cambiamenti ViewModel, è necessario allegare alla manifestazione di ViewModel PropertyChanged
e CollectionChanged
caso gli elementi selezionati. naturalmente è possibile farlo in codebehind, ma in questo caso vorrei creare qualcosa di più riutilizzabile:
//ViewModel
public ObservableCollection<YourBusinessItem> SelectedObject {get; set;}
//in codebehind:
var binder = new SelectedItemsBinder(listview, viewmodel.SelectedItems);
binder.Bind();
o creare proprietà associata personalizzato, in modo da poter utilizzare la sintassi obbligatorio in 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);
}
}
}
proprietà associata implementazione
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);
}
}
Grazie mille, mi ha aiutato molto :) –
Grazie per il codice. Dovresti anche gestire il reset della raccolta nel metodo Collection_CollectionChanged. –