Nano Hash - криптовалюты, майнинг, программирование

Строка сведений о сворачивании сетки данных WPF при нажатии

Мне нужно было свернуть строку сведений WPF DataGrid, когда пользователь щелкнул ее, и повторно отобразить ее, когда они снова щелкнули. Я также хотел сохранить DataGridRoDetailsVisibilityMode VisibleWhenSelected, используя одиночный выбор.

Я придумал это решение, основанное на этом сообщении в другом месте: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0a45b3a7-46d0-45a9-84b2-0062f07f6fec#eadc8f65-fcc6-41df-9ab9-8d93993e114c

    private bool _rowSelectionChanged;


    private void dgCompletedJobs_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        _rowSelectionChanged = true;
    }

    private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        DependencyObject dep = (DependencyObject)e.OriginalSource;

        //navigate up the tree
        while (dep != null &&
            !(dep is DataGridCell) &&
            !(dep is DataGridColumnHeader))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        if (dep == null)
        {
            return;
        }

        DataGridCell dgc = dep as DataGridCell;
        if (dgc != null)
        {
            //navigate further up the tree
            while (dep != null && !(dep is DataGridRow))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            DataGridRow dgr = dep as DataGridRow;
            DataGrid dg = sender as DataGrid;
            if (dg != null && dgr != null)
            {
                if (dgr.IsSelected && !_rowSelectionChanged)
                {
                    dg.RowDetailsVisibilityMode =
                        (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected)
                            ? DataGridRowDetailsVisibilityMode.Collapsed
                            : DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
                }
                else
                {
                    dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
                }
            }
        }
        _rowSelectionChanged = false;
    }

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

У кого-нибудь есть более чистое решение?


Ответы:


1

Чтобы сделать это с «правильным» MVVM, вы должны привязать RowDetailsVisibilityMode к свойству модели представления:

<DataGrid x:Name="dgCompletedJobs" RowDetailsVisibilityMode="{Binding RowDetailsVisible}"/>

Ваше свойство модели представления будет выглядеть примерно так:

private DataGridRowDetailsVisibilityMode _rowDetailsVisible;
public DataGridRowDetailsVisibilityMode RowDetailsVisible
{
    get { return _rowDetailsVisible; }
    set {
        _rowDetailsVisible = value;
        if (PropertyChanged != null) {
             PropertyChanged(this, new PropertyChangedEventArgs("RowDetailsVisible"));
        }
    }
}

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

private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Window1ViewModel viewModel = (Window1ViewModel)DataContext;
    if (viewModel.RowDetailsVisible == DataGridRowDetailsVisibilityMode.Collapsed) {
        viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
    } else {
        viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.Collapsed;
    }
}
13.11.2012
  • Работал отлично. Спасибо. 26.02.2016
  • В действительно чистом MVVM — если вы хотите повторно использовать виртуальную машину вне WPF — виртуальная машина не должна зависеть от System.Windows.Controls, откуда DataGridRowDetailsVisibilityMode. 20.02.2021
  • @Jinjinov да, создайте свойство Boolean или Enum в модели представления и используйте преобразователь. Оставлено читателю в качестве упражнения. 30.04.2021

  • 2

    Почему бы вам не использовать параметр отправителя? Если событие определено в DataGrid, отправителем всегда является DataGrid! Используйте безопасный бросок en check для null, чтобы быть безопасным, но это должно сработать.

    Код кажется ненужным сложным, поскольку вы возвращаетесь от исходного источника к своей DataGrid через визуальное дерево.

            private void dataGridMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            DataGrid dg = sender as DataGrid;
            if (dg == null)
                return;
            if (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected)
                dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed;
            else
                dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
        }
    
    13.11.2012
  • Это не работает должным образом, когда вы выбираете другую строку — в новой выбранной строке отображаются детали в зависимости от состояния деталей в предыдущей строке. 20.02.2021

  • 3

    Я придумал другой способ, но не «правильный» способ MVVM, поскольку он использует код позади (как и некоторый код в предложенных ответах выше), но он делает трюк всего с несколькими строками кода.

    Кодируя событие PreviewMouseUp, я смог получить именно то поведение, которое мне было нужно. Код гарантирует, что вы на самом деле нажали на что-то в сетке, и чтобы свернуть, это должна быть та же самая строка, которая уже открыта.

     private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            DataGrid grid = sender as DataGrid;
    
            if (grid != null)
            {
                FrameworkElement element = e.OriginalSource as FrameworkElement;
    
                if (element?.DataContext is MyCustomObject)
                {
                    if (grid.SelectedItem == (MyCustomObject) ((FrameworkElement) e.OriginalSource).DataContext)
                    {
                        grid.SelectedIndex = -1;
                        e.Handled = true;
                    }
                }
            }
        }
    
    14.08.2015

    4

    Это объединяет ответ от Grafix с ответом от Prethen.

    Используйте его, если вы хотите, чтобы детали строки переключались только тогда, когда строка уже выбрана:

    private void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (sender is DataGrid dataGrid && 
            e.OriginalSource is FrameworkElement frameworkElement && 
            frameworkElement.DataContext == dataGrid.SelectedItem)
        {
            if (dataGrid.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected)
                dataGrid.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed;
            else
                dataGrid.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
        }
    }
    
    20.02.2021
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..