2010-04-10 5 views
14

У меня есть datagrid, который включен с поддержкой multi-select. Мне нужно изменить выбор в viewmodel. Однако свойство SelectedItems доступно только для чтения и не может быть напрямую привязано к свойству в viewmodel. Итак, как мне сигнализировать о том, что выбор изменился?WPF DataGrid multiselect binding

+0

Смотрите также http://stackoverflow.com/questions/1579700/wpf-toolkit-datagrid-multi-select-how-to-get-selecteditems-out –

ответ

6

Я не работал с DataGrid много, но один метод, который работает для ListView является привязка к IsSelected собственности индивидуального ListViewItem. Просто установите для этого параметра значение true для каждого объекта в вашем списке, а затем он будет выбран.

Возможно, объект, представляющий строку в DataGrid, также имеет свойство IsSelected и может быть использован таким же образом?

17

Энди правильный. DataGridRow.IsSelected - свойство зависимостей, которое может быть привязано к базе данных для управления выбором из ViewModel. Следующий пример кода демонстрирует это:

<Window x:Class="DataGridMultiSelectSample.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <tk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" EnableRowVirtualization="False"> 
      <tk:DataGrid.Columns> 
       <tk:DataGridTextColumn Header="Value" Binding="{Binding Value}" /> 
      </tk:DataGrid.Columns> 
      <tk:DataGrid.RowStyle> 
       <Style TargetType="tk:DataGridRow"> 
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
       </Style> 
      </tk:DataGrid.RowStyle> 
     </tk:DataGrid> 
     <Button Content="Select Even" Click="Even_Click" /> 
     <Button Content="Select Odd" Click="Odd_Click" /> 
    </StackPanel> 
</Window> 

using System.ComponentModel; 
using System.Windows; 

namespace DataGridMultiSelectSample 
{ 
    public partial class Window1 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      DataContext = new[] 
           { 
            new MyViewModel {Value = "Able"}, 
            new MyViewModel {Value = "Baker"}, 
            new MyViewModel {Value = "Charlie"}, 
            new MyViewModel {Value = "Dog"}, 
            new MyViewModel {Value = "Fox"}, 
           }; 
     } 

     private void Even_Click(object sender, RoutedEventArgs e) 
     { 
      var array = (MyViewModel[]) DataContext; 
      for (int i = 0; i < array.Length; ++i) 
       array[i].IsSelected = i%2 == 0; 
     } 

     private void Odd_Click(object sender, RoutedEventArgs e) 
     { 
      var array = (MyViewModel[])DataContext; 
      for (int i = 0; i < array.Length; ++i) 
       array[i].IsSelected = i % 2 == 1; 
     } 
    } 

    public class MyViewModel : INotifyPropertyChanged 
    { 
     public string Value { get; set; } 

     private bool mIsSelected; 
     public bool IsSelected 
     { 
      get { return mIsSelected; } 
      set 
      { 
       if (mIsSelected == value) return; 
       mIsSelected = value; 
       if (PropertyChanged != null) 
        PropertyChanged(this, new PropertyChangedEventArgs("IsSelected")); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 
} 

Обязательно установите EnableRowVirtualisation="False" на элементе DataGrid, иначе есть риск, что привязки IsSelected выпадают из неисправных.

+0

совершенен. И спасибо за образец кода - это хорошо иллюстрирует. –

+0

Спасибо. Надеюсь, вы не возражаете, что добавьте в ваш пример 'EnableRowVirtualisation =" False "', потому что без него есть ошибка, где привязка не относится к новым строкам. –

3

Ребята, спасибо за помощь. Моя проблема решена. Я думаю, что эта проблема довольно часто встречается у новых разработчиков WPF, поэтому я снова остановлюсь на своей проблеме, а также на решении более подробно, на случай, если кто-то другой столкнется с такими же проблемами.

Проблема: У меня есть многоэкранный включенный файл данных аудиофайлов. Сетка имеет несколько заголовков столбцов. Пользователь может многократно выбирать несколько строк. Когда он нажимает кнопку «Воспроизведение», звуковые файлы будут воспроизводиться в порядке очереди заголовков столбцов (скажем, столбец A). Когда воспроизведение начинается, мультивыбор очищается, и выделяется только текущий воспроизводимый файл. Когда воспроизведение будет завершено для всех файлов, будет отображен многоэкранный выбор. Воспроизведение выполняется в режиме просмотра. Как вы можете видеть, здесь есть две проблемы: 1) как выбрать текущий воспроизводимый файл из режима просмотра, и 2) как подать сигнал на представление из режима просмотра, что воспроизведение завершено, и повторно отобразить мультивыбор.

Решение: Чтобы решить первую проблему, я создал свойство в модели view, которое привязано к свойству SelectedIndex, чтобы выбрать текущий воспроизводимый файл. Чтобы решить вторую проблему, я создал логическое свойство в модели представления, чтобы показать, что воспроизведение закончено. В коде представления, я подписался на событие PropertyChanged объекта boolean. В обработчике события свойство SelectedItems вида воссоздается из сохраненного множественного выбора (содержимое SelectedItems было сохранено в списке, а SelectedItems было очищено при запуске воспроизведения). Сначала у меня возникли проблемы с повторным созданием SelectedItems. Оказалось, что проблема связана с тем, что повторное создание было инициировано через второй поток. WPF этого не допускает. Решение этого - использовать Dispatcher.Invoke(), чтобы основной поток выполнял работу. Это может быть очень простой проблемой для опытных разработчиков, но для новичков это небольшая проблема. Во всяком случае, много помощи от разных людей.

2

Просто используйте SelectedItems для любого производного класса MultiSelector и используйте методы Add, Remove, Clear on IList, который он возвращает.

С уважением, Робин