Как связать множественный выбор списка в viewmodel? - PullRequest
34 голосов
/ 21 апреля 2011

Я реализую список и кнопку рядом с ним. Я должен иметь возможность, что когда я выбираю несколько элементов в списке, а затем нажимаю на кнопку, выбранные элементы помещаются в список. Но мой вопрос, как мне привязать выбранные элементы к модели представления? Я изменил свой режим выбора на несколько. Но тогда, я просто должен сделать:

SelectedItem={Binding path= selectedItems}

и затем сделайте в моей viewmodel свойство selectedItems, и оно установит эти элементы, которые я выбрал? Или как правильно это сделать?

Ответы [ 9 ]

36 голосов
/ 22 сентября 2014

Как Доктор уже указал, вы можете привязать SelectedItems к XAML CommandParameter

После долгих поисков и поисков, янаконец-то нашли простое решение этой распространенной проблемы.

Чтобы заставить ее работать, вы должны следовать ВСЕМ следующим правилам :

  1. После Предложение Эд Болла ', для вашей привязки данных команды XAML определите CommandParameter свойство BEFORE Command свойство.Это очень трудоемкая ошибка.

    enter image description here

  2. Убедитесь, что ICommand * CanExecute и Выполнить методы имеют параметр типа object .Таким образом, вы можете предотвратить отключение исключений приведения, возникающих всякий раз, когда тип привязки данных CommandParameter не соответствует типу параметра вашего командного метода.

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

Например, вы можете либо отправить свойство listview / listbox SelectedItems вам ICommand методами, либо listview / listbox егосамостоятельно.Отлично, не правда ли?

Надеюсь, это не позволит кому-то потратить огромное количество времени, которое я потратил, чтобы выяснить, как получить SelectedItems в качестве CanExecute параметра.*

22 голосов
/ 21 апреля 2011

Это довольно сложно сделать Mutliple Selection в MVVM, потому что свойство SelectedItems не является Dependency Property.Тем не менее, есть некоторые приемы, которые вы можете использовать.Я обнаружил эту триологию постов в блоге, в которых подробно описан вопрос и представлены полезные решения.

Надеюсь, это поможет

13 голосов
/ 14 мая 2014

Если вы уже используете System.Windows.Interactivity и Microsoft.Expression.Interactions, здесь есть обходной путь без какого-либо другого кода / поведения, чтобы возиться. Если вам это нужно, его можно загрузить с здесь

В этом обходном пути используются триггер события интерактивности и механизм свойств набора взаимодействий в вышеприведенных сборках.

Дополнительное объявление пространства имен в 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>

Просмотр модели:

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);
      }
    }
  }
}

В приведенном выше примере ваша ViewModel будет подбирать выбранные элементы всякий раз, когда изменяется выбор в ListView.

12 голосов
/ 21 апреля 2011

Что вы можете сделать, так это то, что вы можете обрабатывать Button_Click (...) в своем коде. Затем в этом методе code-behind вы можете создать список выбранных элементов, перебирая выбранные элементы listView.

Поскольку разрешен доступ к ViewModel из View, теперь вы можете вызывать метод в ViewModel и передавать список выбранных элементов в качестве параметра.

Я не уверен, будет ли это работать также только с Bindings, однако неплохо использовать и кодовый код.

Пример кода:

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);
}

EDIT

Вот минималистский пример, XAML:

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

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

КОД-ЗА:

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);
    }
6 голосов
/ 21 апреля 2011

К сожалению, SelectedItems - это свойство, не предназначенное только для чтения.

В этой статье я нашел много помощи Как связать данные со свойством SelectedItems в WPF

4 голосов
/ 14 апреля 2014

Вы не можете связать, но вы можете отправить в Command как CommandParameter.

3 голосов
/ 25 октября 2012

Если вы используете Metro/WinRT, возможно, вы захотите взглянуть на WinRTXXAMLToolkit , поскольку он предлагает привязываемое свойство зависимости SelectedItems в качестве одного из его расширений.

0 голосов
/ 17 июня 2015

Я сделал решение для этого, для меня это было достаточно просто.

<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>

Тогда в viewmodel:

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

SelectedModels - список, в котором я хотел выбратьбыть заполненным.

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

         SelectedModels = tempModelInfo;
    }
0 голосов
/ 15 ноября 2013

Как небольшое изменение в посте Кристиана, я реализовал похожий код, используя событие ListView.SelectionChanged.Вместо вызова метода в ViewModel я установил свойство 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;
}

Таким образом, ViewModel.SelectedItems доступен для любой команды, которая может быть в ваших ViewModel и может использоваться для привязки данных (если вы превратите их в ObservableCollection).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...