MultiSelection no funciona en ListView

I have problem in ListView MultiSelection.

Aquí está mi código:

   private ICommand _excludeCurveCommand;


    public ICommand ExcludeCurveCommand
    {
        get
        {
            if (_excludeCurveCommand == null)
                _excludeCurveCommand = new DelegateCommand<object>(param => this.ExcludeCurveExecuted(param));

            return _excludeCurveCommand;
        }
    }

    /// <summary>
    /// Executed event for ContextMenu --> Remove click
    /// </summary>
    /// <param name="param">param is FolderItemViewModel bound as CommandParameter</param>
    private void ExcludeCurveExecuted(object param)
    {

        ICollection<object> curves = param as ICollection<object>;
        int count =  curves.Count;
    }



 < Button Content="Exclude" Command="{Binding ExcludeCurveCommand}" CommandParameter="{Binding SelectedItems,ElementName=lstView}" .../>

< ListView Name="lstView"  ItemsSource="{Binding MyList}" SelectionMode="Extended" ..../>

Here i used shift and selected from first four items. But in ExcludeCurveExecuted method i getting some random counts always. What is the issue in this.

EDIT: * I don't wantto go with IsSelected flag in ViewModel

preguntado el 31 de enero de 12 a las 08:01

I don't know what is happening. After i re-factor the code, its working as expected. But i don't find any major changes. hhhm no clue. Any way its working now. -

2 Respuestas

To me it seems that you have have ListView UI virtualization enabled, as it enabled by default. That means, that ListView draws only items visible on UI.

Here is MSDN enlace

To be sure what is going on interface (like selection in your case) I'm afraid you don't have any other option then

  • or disable UI virtualization (not good)

  • o implementar IsSelected flag on ModelView

Buena suerte.

Respondido el 31 de enero de 12 a las 13:01

Well i added the IsSelected flag at last, but working with out that. - Mohanavel

You can use a Behavior to Sync the Selected Items to a Collection in Your View Model....

You a ve to add a reference to System.Windows.Interactivity to your project as well as an alias to it in your Xaml

Beahvior

public class MultiSelectionBehavior : Behavior<ListView>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            if (SelectedItems != null)
            {
                AssociatedObject.SelectedItems.Clear();
                foreach (var item in SelectedItems)
                {
                    AssociatedObject.SelectedItems.Add(item);
                }
            }
        }

public IList SelectedItems
{
    get { return (IList)GetValue(SelectedItemsProperty); }
    set { SetValue(SelectedItemsProperty, value); }
}

public static readonly DependencyProperty SelectedItemsProperty =
    DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionBehavior), new UIPropertyMetadata(null, SelectedItemsChanged));

private static void SelectedItemsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    var behavior = o as MultiSelectionBehavior;
    if (behavior == null)
        return;

    var oldValue = e.OldValue as INotifyCollectionChanged;
    var newValue = e.NewValue as INotifyCollectionChanged;

    if (oldValue != null)
    {
        oldValue.CollectionChanged -= behavior.SourceCollectionChanged;
        behavior.AssociatedObject.SelectionChanged -= behavior.ListViewSelectionChanged;
    }
    if (newValue != null)
    {
        behavior.AssociatedObject.SelectedItems.Clear();
        foreach (var item in (IEnumerable)newValue)
        {
            behavior.AssociatedObject.SelectedItems.Add(item);
        }

        behavior.AssociatedObject.SelectionChanged += behavior.ListViewSelectionChanged;
        newValue.CollectionChanged += behavior.SourceCollectionChanged;
    }
}

private bool _isUpdatingTarget;
private bool _isUpdatingSource;

void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (_isUpdatingSource)
        return;

    try
    {
        _isUpdatingTarget = true;

        if (e.OldItems != null)
        {
            foreach (var item in e.OldItems)
            {
                AssociatedObject.SelectedItems.Remove(item);
            }
        }

        if (e.NewItems != null)
        {
            foreach (var item in e.NewItems)
            {
                AssociatedObject.SelectedItems.Add(item);
            }
        }
    }
    finally
    {
        _isUpdatingTarget = false;
    }
}

private void ListViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (_isUpdatingTarget)
        return;

    var selectedItems = this.SelectedItems;
    if (selectedItems == null)
        return;

    try
    {
        _isUpdatingSource = true;

        foreach (var item in e.RemovedItems)
        {
            selectedItems.Remove(item);
        }

        foreach (var item in e.AddedItems)
        {
            selectedItems.Add(item);
        }
    }
    finally
    {
        _isUpdatingSource = false;
    }
}

}

Xaml

    <ListView ItemsSource="{Binding ItemsList}"
             DisplayMemberPath="Name"
             SelectionMode="Extended">
        <i:Interaction.Behaviors>
            <local:MultiSelectionBehavior SelectedItems="{Binding MySelectedItems}" />
        </i:Interaction.Behaviors>
    </ListView>

MySelectedItems is the collection in your ViewModel

Dont forget it initialize ... MySelectedItems in your ViewModel....

Your ViewModel

private void ExcludeCurveExecuted(object param)
{                  
    int count =  MySelectedItems.Count;
} 

Respondido el 31 de enero de 12 a las 13:01

@Mohanavel The Code is already there you just have to use it.... and yes its going to save you a lot of work for the sync Items - Ankesh

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.