Arhn - архитектура программирования

WPF DataGrid DetailView Переключить видимость

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

Когда пользователь щелкает строку в сетке, я разворачиваю ее и открываю элементы управления. Когда они закончат, я бы хотел, чтобы они могли снова щелкнуть строку, чтобы скрыть эту строку сведений. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу заставить WPF различать щелчок по строке (фактически «заголовок» сведений о строке) и область сведений о строке, где находятся все мои элементы управления. Для WPF щелчок по детали означает щелчок по строке, и мой код считает это переключателем и поэтому скрывает строку.

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

ViewModel и модель:

namespace StackOverflow
{
    public class ViewModel
    {
        public ObservableCollection<MyClass> MyCollection { get; set; }

        public ViewModel()
        {
            MyCollection = new ObservableCollection<MyClass>
            {
                new MyClass(0, "Foo"),
                new MyClass(1, "Bar")
            };
        }
    }

    public class MyClass
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public MyClass(int id, string name)
        {
            Id = id;
            Name = name;
        }
    }
}

Вид:

<Window x:Class="StackOverflow.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:StackOverflow"
    mc:Ignorable="d"
    Title="MainWindow"
    Height="350"
    Width="525">
<Window.Resources>
    <local:ViewModel x:Key='MyVM'></local:ViewModel>
</Window.Resources>
<Grid DataContext='{StaticResource MyVM}'>
    <DataGrid HorizontalAlignment='Center' Width='200' Margin='20'
              RowDetailsVisibilityMode='Collapsed'
              ItemsSource='{Binding MyCollection}'>
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <EventSetter Event="UIElement.PreviewMouseLeftButtonDown"
                             Handler="OnRowLeftClicked" />
            </Style>

        </DataGrid.RowStyle>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <StackPanel Background='LightBlue' HorizontalAlignment='Center' Orientation='Horizontal' Height='100'>
                    <Button VerticalAlignment='Center'
                            HorizontalAlignment='Center'>Do stuff to this specific item</Button>
                </StackPanel>
            </DataTemplate>

        </DataGrid.RowDetailsTemplate>
    </DataGrid>

</Grid>

Codebehind

namespace StackOverflow
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private DataGridRow lastRowClicked;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnRowLeftClicked(object sender, RoutedEventArgs e)
        {
            var clickedRow = (DataGridRow)sender;

            //If a Todo has been clicked before for this selected user, we need to decide whether a new Todo has been selected.
            if (lastRowClicked != null)
            {
                //If the Todo that was clicked last time is the same as the one that was just clicked, toggle its visibility --- this is where problem lies
                if (lastRowClicked == clickedRow)
                {
                    if (clickedRow.DetailsVisibility == Visibility.Collapsed)
                        clickedRow.DetailsVisibility = Visibility.Visible;
                    else
                        clickedRow.DetailsVisibility = Visibility.Collapsed;
                }
                //If this Todo was not clicked last time, hide the last Todo and show this current one.
                else
                {
                    lastRowClicked.DetailsVisibility = Visibility.Collapsed;
                    clickedRow.DetailsVisibility = Visibility.Visible;
                }
            }
            //If this is the first Todo that was clicked for this user, we can show it without collapsing another row.
            else
            {
                clickedRow.DetailsVisibility = Visibility.Visible;
            }

            //in any case, save the currently clicked row for next time
            lastRowClicked = clickedRow;
        }
    }
}

Обновлять:

Это было помечено как возможный дубликат для мне нужен шаблон Expand/Collapse для RowDetailsTemplate

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


  • Когда открывается дочерний элемент, можете ли вы установить IsHitTestVisible = false для родителя? 06.10.2017
  • Возможный дубликат Мне нужен шаблон Expand/Collapse для RowDetailsTemplate 06.10.2017
  • @EdPlunkett Проблема с изменением IsHitTestVisible заключается в том, что строка и деталь обрабатываются как один и тот же объект. Поэтому, если я установлю для этого значения значение false, я не смогу позже свернуть детали. Что я мог бы сделать, так это заменить шаблон строки сетки данных и окружить ячейки кнопкой и установить обработчики событий на эту кнопку (а не на всю строку, которая включает детали), но это кажется большой работой. 06.10.2017

Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..