Comment lier plusieurs sélections de listview à viewmodel?

J'implémente un listview, et un bouton à côté. J'ai de pouvoir que lorsque je sélectionne plusieurs éléments dans une liste, puis cliquez sur un bouton, puis les éléments sélectionnés sont mis dans une liste. Mais ma question est , comment puis-je lier les éléments sélectionnés vers le viewmodel? J'ai changé mon selectionmode à plusieurs. Mais alors, dois-je juste faire:

SelectedItem={Binding path= selectedItems}

Et puis faire dans mon viewmodel une propriété selectedItems, et il va définir ces éléments que j'ai sélectionnés? Ou qu'est-ce que le droit solution pour ce faire?

32
demandé sur H.B. 2011-04-21 11:53:38

9 réponses

Ce que vous pouvez faire est que vous pouvez gérer le Button_Click(...) dans votre code-derrière. Ensuite, dans cette méthode de code-behind, vous pouvez créer une liste d'éléments sélectionnés en itérant sur les éléments sélectionnés de listView.

Comme il est autorisé à accéder au ViewModel depuis la vue, vous pouvez maintenant appeler une méthode sur votre ViewModel et passer la liste des éléments sélectionnés en tant que paramètre.

Je ne suis pas sûr si cela fonctionnerait aussi avec des liaisons seulement, mais ce n'est pas une mauvaise pratique d'utiliser code-behind as Bien.

Exemple De Code:

public void Button_Click(object sender, EventArguments arg)
{
  List<ListViewItem> mySelectedItems = new List<ListViewItem>();

  foreach(ListViewItem item in myListView.SelectedItems)
  {
    mySelectedItems.Add(item);
  }

  ViewModel.SomeMethod(mySelectedItems);
}

Modifier

Voici un exemple minimaliste, XAML:

<DataTemplate
            x:Key="CarTemplate"
            DataType="{x:Type Car}">
</DataTemplate>

<ListView x:Name="myListView"
          ItemsSource="{Binding Path=Cars}"
          ItemTemplate="{StaticResource CarTemplate}">
</ListView>

CODE-DERRIÈRE:

public void Button_Click(object sender, EventArguments arg)
    {
      List<Car> mySelectedItems = new List<Car>();

      foreach(Car item in myListView.SelectedItems)
      {
        mySelectedItems.Add(item);
      }

      ViewModel.SomeMethod(mySelectedItems);
    }
12
répondu Christian 2015-07-02 15:36:30

Comme Médecin l'a déjà souligné, vous pouvez lier SelectedItems XAML CommandParameter

Après beaucoup de creuser et de googler, j'ai finalement trouvé une solution simple à ce problème commun.

Pour le faire fonctionner, vous devez , suivre TOUTES les règles suivantes:

  1. Suivant la suggestion de Ed Ball ', sur votre liaison de données de commande XAML, définissez CommandParameterpropriété avant Commande propriété. Ce un bug très chronophage.

    entrez la description de l'image ici

  2. Assurez-vous que votre ICommand's CanExecute et Exécuter méthodes ont un paramètre de object type. De cette façon, vous pouvez empêcher les exceptions silenced cast qui se produisent lorsque le type databinding CommandParameter ne correspond pas au type de paramètre de votre méthode de commande.

    private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)
    {
        // Your goes here
    }
    
    private bool OnDeleteSelectedItemsExecute(object SelectedItems)
    {
        // Your goes here
    }
    

Par exemple, vous pouvez envoyer la propriété SelectedItems d'une listview/listbox pour vous ICommand méthodes ou le listview / listbox lui-même. Grande, n'est-ce pas?

Espère qu'il empêche quelqu'un de dépenser de l'énorme quantité de temps que j'ai fait pour comprendre comment recevoir SelectedItems, comme CanExecute paramètre.

30
répondu Julio Nobre 2017-05-23 12:18:06

Il est un peu difficile de faire cette sélection multiple dans MVVM, car la propriété SelectedItems n'est pas un Dependency Property. Cependant, il y a quelques astuces que vous pouvez utiliser. J'ai trouvé cette triologie de messages de blog qui décrivent la question dans certains détails et fournissent des solutions utiles.

J'espère que cela aide

21
répondu AbdouMoumen 2011-04-21 08:51:04

Si vous utilisez le système.Windows.Interactivité et Microsoft.Expression.Interactions déjà, voici une solution de contournement sans autre code / comportement à déranger. Si vous en avez besoin, il peut être téléchargé à partir de ici

Cette solution de contournement utilise le mécanisme de propriété interactivity event trigger et interactions set dans les assemblys ci-dessus.

Déclaration d'espace de noms supplémentaire dans XAML

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

XAML:

<ListView Name="MyListView" ItemsSource="{Binding ModelList}" DisplayMemberPath="Name"  Grid.Column="0">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedItems" Value="{Binding Path=SelectedItems, ElementName=MyListView}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListView>

Vue Modèle:

public class ModelListViewModel
{
  public ObservableCollection<Model> ModelList { get; set; }
  public ObservableCollection<Model> SelectedModels { get; set; }

  public ModelListViewModel() {
    ModelList = new ObservableCollection<Model>();
    SelectedModels = new ObservableCollection<Model>();
  }

  public System.Collections.IList SelectedItems {
    get {
      return SelectedModels;
    }
    set {
      SelectedModels.Clear();
      foreach (Model model in value) {
        SelectedModels.Add(model);
      }
    }
  }
}

Dans l'exemple ci-dessus, votre ViewModel sélectionnera les éléments sélectionnés Chaque fois que la sélection sur ListView a changé.

12
répondu techhero 2014-05-14 18:52:27

Malheureusement, SelectedItems est une propriété non bindable en lecture seule.

J'ai trouvé beaucoup d'aide de cet article Comment Databind à une propriété SelectedItems dans WPF

6
répondu Dummy01 2011-04-21 07:58:37

Vous ne pouvez pas lier, mais vous pouvez envoyer à la commande en tant que CommandParameter.

4
répondu Doctor 2014-04-14 10:58:35

Si vous utilisez Metro/WinRT vous pouvez regarder le WinRTXXAMLToolkit car il offre une bindable SelectedItems la propriété de dépendance comme l'une de ses extensions.

3
répondu technicalflaw 2012-10-25 16:11:05

J'ai fait une solution pour cela, pour moi c'était assez simple.

<ListBox ItemsSource="{Binding ListOfModel}" x:Name="ModelList"
                                SelectedItem="{Binding SelectedModel, Mode=TwoWay}">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="SelectionChanged">
                                    <i:InvokeCommandAction Command="{Binding ExecuteListBoxSelectionChange}" CommandParameter="{Binding ElementName=ModelList}">
                                    </i:InvokeCommandAction>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </ListBox>

, Puis dans le viewmodel:

public ICommand ExecuteListBoxSelectionChange { get; private set; }
ExecuteListBoxSelectionChange = DelegatingCommand<ListBox>.For(ListBoxSelectionChnageEvent).AlwaysEnabled();

SelectedModels est la liste où je voulais que la sélection soit remplie.

    private void ListBoxSelectionChnageEvent(ListBox modelListBox)
    {
        List<ModelInfo> tempModelInfo = new List<ModelInfo>();
         foreach(ModelInfo a in modelListBox.SelectedItems)
             tempModelInfo.Add(a);

         SelectedModels = tempModelInfo;
    }
0
répondu Manas S 2015-06-17 17:36:16

Comme une légère variation sur le post de Christian, j'ai implémenté un code similaire en utilisant le ListView.Événement SelectionChanged. Au lieu d'appeler une méthode sur ViewModel, j'ai défini une propriété appelée SelectedItems:

public void ListView_SelectionChanged( object s, SelectionChangedEventArgs e ) {
    List<Car> mySelectedItems = new List<Car>();

    foreach( Car item in myListView.SelectedItems )
        mySelectedItems.Add(item);

    ViewModel.SelectedItems = mySelectedItems;
}

De cette façon, ViewModel.SelectedItems est disponible pour toute commande que vous pourriez avoir dans votre ViewModel et il peut être utilisé pour la liaison de données (si vous le transformez en ObservableCollection).

-1
répondu Mitkins 2013-11-15 12:20:40