предотвращение изменения строки в сетке данных - PullRequest
9 голосов
/ 26 июля 2011

Я исследовал это и нахожусь в тупике: у меня есть WPF DataGrid и использую модель MVVM.Я хочу, при определенных обстоятельствах, предотвратить возможность изменения строки в DataGrid.Я исследовал это и попробовал методы, подобные найденному здесь .

На практике это работает, однако есть нежелательное «мерцание» (оно выбирает строку, по которой щелкнули, затемвозвращает к предыдущему выбору), хотя это и является близким решением, я бы хотел, чтобы был более элегантный способ, например вообще предотвратить изменение строки.

Я удивлен, что нет SelectionChanging или BeforeSelectionChanged, поэтому я могу отменить событие от запуска;и принудительное предотвращение изменения индекса в моей модели представления, похоже, не имеет никакого значения.

Как я могу это сделать?

Спасибо.

Ответы [ 3 ]

6 голосов
/ 26 июля 2011

что произойдет, если вы возьмете события previewkeydown и previewmousedown и просто вызовете e.Handled=true при определенных обстоятельствах?

Редактировать: чтобы удовлетворить стиль mvvm: вы можете создать Behavior сDependencyProperty, с которым вы можете связать свои обстоятельства.в этом поведении вы можете обрабатывать события и, возможно, некоторые другие вещи, например, нажимает ли пользователь на данные или заголовок ...

2 голосов
/ 11 января 2012

DispatcherPriority был установлен в ContextIdle.Это заставляет вас мерцать, так как ваш SelectedItem установлен дважды (и он был обработан дважды).Просто установите приоритет на Normal, и вы не будете больше мерцать.

0 голосов
/ 24 сентября 2013

Есть несколько примеров для метода PreviewMouseDown здесь .

Общее согласие состоит в том, что возврат DataGrid.SelectedItem к его исходному значению внутри обработчика SelectionChanged в таблице данных не работает должным образом;все примеры кода, которые, кажется, работают, откладывают отмену, попросив Диспетчера запланировать это позже.

У вас есть CellStyle в вашей сетке данных?Для меня сработало следующее:

xaml:

<DataGrid.CellStyle>
    <Style TargetType="{x:Type DataGridCell}">
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="DarkSlateBlue"/>
                <Setter Property="Foreground" Value="White"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</DataGrid.CellStyle>

codebehind:

private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.AddedItems.Count > 0)
    {
        object x = e.AddedItems[0];
        if (x is MyObjectType && x != myViewModel.CurrentItem &&
            myViewModel.ShouldNotDeselectCurrentItem())
        {
            // this will actually revert the SelectedItem correctly, but it won't highlight the correct (old) row.
            this.MyDataGrid.SelectedItem = null;
            this.MyDataGrid.SelectedItem = myViewModel.CurrentItem; 
        }
    }
}

Дело в том, что событие SelectedCellsChanged сработало после события SelectionChanged - ив частности, этот параметр SelectedItem не корректно обновляет SelectedCells, которые являются свойством только для чтения, так что больше кода:

private void MyDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
    List<DataGridCellInfo> selectedCells = MyDataGrid.SelectedCells.ToList();

    List<MyObjectType> wrongObjects = selectedCells.Select(cellInfo => cellInfo.Item as MyObjectType)
        .Where (myObject => myObject != myViewModel.CurrentItem).Distinct().ToList();
    if (wrongObjects.Count > 0)
    {
        MyDataGrid.UnselectAllCells();
        MyDataGrid.SelectedItem = null;
        MyDataGrid.SelectedItem = myViewModel.CurrentItem;
    }
}

Очевидно, что обработчики должны быть подключены к соответствующим событиям в данныхgrid.

Это сработало, как и ожидалось, при желании отменило изменение выделения должным образом и не произвело мерцания.

...