Установите несколько флажков на левую кнопку мыши и перетащите в wpf - PullRequest
0 голосов
/ 03 октября 2018

Я хочу переключить состояние проверки всех флажков в wpf DataGrid, когда пользователь перетаскивает его, когда левая кнопка мыши нажата.Это означает, что когда пользователь нажимает левую кнопку мыши и перетаскивает DataGrid, все ячейки типа 'DataGridCheckBoxColumn', попадающие в эту область перетаскивания, должны изменить состояние проверки.

Я могу добиться этого, получивсбор выделенных ячеек и переключение состояния флажка, но он работает нормально только в том случае, если в сетке мало строк и отсутствует вертикальная полоса прокрутки.Когда я добавляю больше строк в сетку, чтобы на сетке присутствовала вертикальная полоса прокрутки, этот метод не работает.Он переключает флажки в области перетаскивания и множество других флажков вниз по области просмотра сетки (это своего рода область подкачки, как будто DataGrid делит окно на несколько страниц и выбирает эти флажки на каждой странице).

Что я пробовал

  1. переключать флажки, получая коллекцию SelectedCells
  2. Переключать, получая флажки под синим прямоугольником выбора из VisualTreeHelper
  3. Переключение между циклами строк и столбцов, находящихся в области перетаскивания, путем получения индексов строк и столбцов

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

.xaml

<Window x:Class="MultipleCheckboxSelection.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MultipleCheckboxSelection"
    mc:Ignorable="d"
    Title="MainWindow" Height="500" Width="800">
<Grid>
    <DataGrid AutoGenerateColumns="False" Margin="0,0,0,29" Name="userGrid" SelectionUnit="Cell" 
              PreviewMouseLeftButtonUp="userGrid_PreviewMouseLeftButtonUp" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"></DataGridTextColumn>
            <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"></DataGridTextColumn>
            <DataGridTextColumn Header="Age" Binding="{Binding Age}" Width="100"/>
            <DataGridCheckBoxColumn Header="Column-1"></DataGridCheckBoxColumn>
            <DataGridCheckBoxColumn Header="Column-2"></DataGridCheckBoxColumn>
            <DataGridCheckBoxColumn Header="Column-3"></DataGridCheckBoxColumn>
            <DataGridCheckBoxColumn Header="Column-4"></DataGridCheckBoxColumn>
            <DataGridCheckBoxColumn Header="Column-5"></DataGridCheckBoxColumn>
            <DataGridCheckBoxColumn Header="Column-6"></DataGridCheckBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

C #

public partial class MainWindow : Window
{
    readonly ObservableCollection<Person> People = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();
        for (int i = 0; i < 2000; i++)
        {
            People.Add(new Person() { FirstName = "First", LastName = "Last", Age = 20 });
        }
        userGrid.ItemsSource = People;
    }

    private void userGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        IList<DataGridCellInfo> selectedCells = userGrid.SelectedCells;

        foreach (var dataGridCell in selectedCells)
        {
            if (dataGridCell.Column is DataGridCheckBoxColumn)
            {
                var checkBox = dataGridCell.Column.GetCellContent(dataGridCell.Item) as CheckBox;
                if (null != checkBox)
                {
                    checkBox.IsChecked = !checkBox.IsChecked;
                }
            }
        }
        userGrid.UnselectAllCells();
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

изображениерезультат для лучшего понимания

Я использую .net 4.6.1.Небольшая помощь будет высоко оценена.

РЕДАКТИРОВАТЬ:

Мое приложение имеет различные типы столбцов флажков.Каждый тип может иметь 0 или более столбцов флажков, которые всегда размещаются вместе.Эти столбцы добавляются пользователем во время выполнения, а также могут быть удалены во время выполнения.Допустим, у меня есть 3 типа столбцов флажков (T1, T2, T3).Все столбцы, добавленные для T1, будут размещены рядом друг с другом и одинаково для двух других типов.Если я сохраню список значений bool в моем контексте данных, мне придется проделать большую работу, чтобы поддерживать правильные значения в списке, поскольку столбцы добавляются и удаляются в определенных позициях.Например, скажем, пользователь удаляет ранее добавленный столбец в позиции 6, тогда мне придется пройтись по всем строкам сетки и перестроить список, удалив значение bool для удаленного столбца.То же самое потребуется, если новый столбец будет вставлен где-то посередине.Это также может не сказаться на производительности.

1 Ответ

0 голосов
/ 03 октября 2018

Проблема в том, что в DataGrid фактические элементы управления флажками «повторно используются».Вместо того, чтобы менять элемент управления флажком, вы должны изменить базовые данные (добавленные к вашему классу персонажа).

Затем выполните привязку следующим образом:

<DataGridCheckBoxColumn Header="Column-1" IsChecked="{Binding IsCheckedColumn1}"/>

Затем вы на самом деле измените базовые данные, какэто:

private void userGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    var selectedItems = userGrid.SelectedItems;

    foreach (var item as Person in selectedItems)
    {
        item.IsCheckedColumn1 = true;
    }
    userGrid.UnselectAllCells();
}

Вам также нужно внедрить INotifyPropertyChanged для вашего личного класса.

РЕДАКТИРОВАТЬ, чтобы ответить на комментарий :

Если у вас естьпеременное количество флажков, которые вы могли бы использовать List<bool>.

Измените значение следующим образом:

item.IsChecked[0] = true;

Вы можете привязать к списку так:

<DataGridCheckBoxColumn Header="Column-1" IsChecked="{Binding IsChecked[0]}"/>
...