Привязка мультивыбора WPF DataGrid

У меня есть datagrid, который является включенным мультивыбором. Я должен изменить выбор в viewmodel. Однако свойство SelectedItems только для чтения и не может быть непосредственно связано со свойством в viewmodel. Таким образом, как я предупреждаю к представлению, что выбор изменился?

14
задан JZ. 10 April 2010 в 22:36
поделиться

3 ответа

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

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

6
ответ дан 1 December 2019 в 09:32
поделиться

Энди прав. 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 выйдут из строя.

17
ответ дан 1 December 2019 в 09:32
поделиться

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

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

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

3
ответ дан 1 December 2019 в 09:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: