WPF Datagrid - кажется, что программный выбор строки нарушает множественный выбор - PullRequest
4 голосов
/ 22 августа 2011

У меня есть элемент управления WPF DataGrid с SelectionUnit «FullRow» и SelectionMode «Extended», в которых я программно выбираю элемент (обычно первый элемент).Выбор работает, но по какой-то причине любая форма программного выбора, по-видимому, нарушает возможность множественного выбора смещением-выбором.

Если я щелкаю один раз по другому элементу в сетке данных (таким образом, элемент, который я только что щелкнул, является единственным выбранным элементом), тогда shift-select будет работать.Кажется, он сломается, только если я программно выбрал элемент.Кроме того, управляющий щелчок работает для выбора нескольких элементов в любом случае - кажется, что только нажатие клавиши shift-select не работает.

Я пробовал различные формы программного выбора одного элемента, начиная с простого:myGrid.SelectedIndex = 0 для использования ItemContainerGenerator в DataGrid для получения экземпляра объекта DataGridRow и установки IsSelected = true на него, но безрезультатно.

Повторное выполнение - программный выбор элемента работает, но это нарушает выбор с нажатой клавишей Shift.

Кто-нибудь сталкивался с этим раньше?Я попытался установить фокус на экземпляре DataGridRow, который выбран программно, но, похоже, это не помогает?

Ответы [ 3 ]

2 голосов
/ 08 декабря 2012

Мне удалось обойти эту проблему с помощью отражения:

var method = typeof(DataGrid).GetMethod("HandleSelectionForCellInput", BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(MyDataGrid, new object[] { cellToSelect, false, false, false });
1 голос
/ 23 августа 2011

Помните, что есть разница между фокусом и фокусом клавиатуры.Когда вы выбираете элемент в коде, проверьте, какой элемент управления имеет фокус клавиатуры / обычную фокусировку.Я предполагаю, что сетка данных теряет этот фокус до тех пор, пока вы не щелкнете по нему мышью, а затем она вновь обретет фокус, необходимый для использования функции ctrl.хостинг внутри приложения C ++.

0 голосов
/ 06 мая 2015

Я только что решил ту же проблему с помощью фрагмента @ ezolotko.Поскольку сетка генерирует строки динамически, мне нужно было подписаться на событие ItemContainerGenerator.StatusChanged и найти первую ячейку в строке, представляющую этот элемент.

Чтобы найти ячейку, я использовал DataGridHelper class и был обернутвсе это в прикрепленном поведении:

using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using Speedwell.WPF.Helpers;

namespace Speedwell.WPF.Behaviors
{
    public static class DataGridSingleRowSelected
    {
        public static readonly DependencyProperty IsSelectionFixEnabledProperty = DependencyProperty.RegisterAttached
        (
            "IsSelectionFixEnabled",
            typeof(bool?),
            typeof(DataGridSingleRowSelected),
            new PropertyMetadata(null, IsSelectionFixEnabledChanged)
        );

        public static bool GetIsSelectionFixEnabled(DataGrid element)
        {
            return (bool)element.GetValue(IsSelectionFixEnabledProperty);
        }

        public static void SetIsSelectionFixEnabled(DataGrid element, bool value)
        {
            element.SetValue(IsSelectionFixEnabledProperty, value);
        }

        private static void IsSelectionFixEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            var dataGrid = sender as DataGrid;
            if(dataGrid != null)
            {
                if(args.OldValue == null)
                {
                    dataGrid.ItemContainerGenerator.StatusChanged += (s, e) => ContainerStatusChanged(dataGrid, ((ItemContainerGenerator)s));
                }
            }
        }

        private static void ContainerStatusChanged(DataGrid dataGrid, ItemContainerGenerator generator)
        {
            if(generator != null && generator.Status == GeneratorStatus.ContainersGenerated && dataGrid.SelectedItems.Count == 1)
            {
                var row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(dataGrid.SelectedItems[0]);
                if(row != null)
                {
                    var cell = dataGrid.GetCell(row, 0);
                    if(cell != null)
                    {
                        SelectCellMethod.Invoke(dataGrid, new object[] { cell, false, false, false });
                    }
                }
            }
        }

        private static readonly MethodInfo SelectCellMethod = typeof(DataGrid).GetMethod("HandleSelectionForCellInput", BindingFlags.Instance | BindingFlags.NonPublic);
    }
}

Как вы можете видеть, правильный выбор применяется только тогда, когда выбрана одна (1) строка, и это именно то, что мне нужно, и кажется, что @Jordan0Day запрашивается.

...