Как я могу составить статический текст «новый класс операций» с объектами с привязкой к данным, перечисленными в сетке данных?

У меня есть сетка данных в моем приложении WPF.

Эта сетка данных привязана к ObservableCollection, которая называется OperationClasses, как определено ниже.

Тип OperationClass состоит из 3 свойств: Name, Start и End соответственно.

Я хотел бы знать, как добавить OperationClass в качестве строки сетки данных в DataGridList, щелкнув последнюю строку с текстом «новый класс операций», как показано на изображении в виде прикрепленного файла. Изображение DataGrid с примерами значений:

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

Как я могу составить статический текст «новый класс операций» с объектами с привязкой к данным, перечисленными в DataGrid?

public ObservableCollection<OperationClass> OperationClasses
{
    get
    {
        return _operationClasses;
    }
    set
    {
        SetProperty(ref _operationClasses, value);
    }
}

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

Возможно, простое ContextMenu поможет?

Yannick 29.12.2022 17:28

Почему бы просто не добавить кнопку под вашей сеткой данных с содержимым «новый класс операции»? Вы можете установить для datagrid CanUserAddRows false. Кнопка добавляет пустой элемент в наблюдаемую коллекцию и устанавливает фокус на первую ячейку.

Andy 29.12.2022 18:15

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

UGURENG 30.12.2022 00:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно указать DataTemplateSelector, чтобы применить выделенный DataTemplate к столбцу-заполнителю.

Прежде всего, необходимо включить элемент-заполнитель (или строку таблицы-заполнителя), установив DataGrid.CanUserAddRows на true. Значение по умолчанию равно true, поэтому просто убедитесь, что вы явно не установили его на false.

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

Следуя вашему коду, в примере предполагается, что модель данных, используемая для заполнения DataGrid, представляет собой OperationClass с двумя вымышленными свойствами для создания двух столбцов:

OperationClass.cs

class OperationClass : INotifyPropertyChanegd
{
  public string TextDataFirstColumn { get; set; }
  public string TextDataSecondColumn { get; set; }
}

Сначала определите DataTemplateSelector:

OperationClassTemplateSelector.cs

class OperationClassTemplateSelector : DataTemplateSelector
{
  public DataTemplate DefaultTemplate { get; set; }
  public DataTemplate PlaceholderTemplate { get; set; }

  public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    => item switch
    {
      OperationClass _ => this.DefaultTemplate,
      var dataItem when dataItem is not null => this.PlaceholderTemplate,
      _ => base.SelectTemplate(item, container),
    };
}

Второй шаг — явно определить шаблоны столбцов. Важно определить столбец, который должен содержать текст-заполнитель, как DataGridTemplateColumn. Это необходимо для того, чтобы разрешить назначение реализации DataTemplateSelector.

В первом столбце строки-заполнителя будет отображаться «Добавить новый элемент...» в качестве текста-заполнителя:

<DataGrid ItemsSource = "{Binding OperationClassItems}"
          AutoGenerateColumns = "False">
  <DataGrid.Columns>
    <DataGridTemplateColumn Header = "1st Column">
      <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate DataType = "{x:Type local:OperationClass}">
          <TextBox Text = "{Binding TextDataFirstColumn}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellEditingTemplate>

      <!-- Instead of defining the CellTemplate explicitly, 
           we assign the CellTemplateSelector instead -->
      <DataGridTemplateColumn.CellTemplateSelector>
        <local:OperationClassTemplateSelector>
          <local:OperationClassTemplateSelector.DefaultTemplate>
            <DataTemplate DataType = "{x:Type local:OperationClass}">
              <TextBlock Text = "{Binding TextDataFirstColumn}" />
            </DataTemplate>
          </local:OperationClassTemplateSelector.DefaultTemplate>

          <local:OperationClassTemplateSelector.PlaceholderTemplate>
            <DataTemplate>
              <TextBlock Text = "Add new item..." />
            </DataTemplate>
          </local:OperationClassTemplateSelector.PlaceholderTemplate>
        </local:OperationClassTemplateSelector>
      </DataGridTemplateColumn.CellTemplateSelector>
    </DataGridTemplateColumn>

    <DataGridTextColumn Header = "2nd Column" 
                        Binding = "{Binding TextDataSecondColumn}" />
  </DataGrid.Columns>
</DataGrid>

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

Перед добавлением нового товара

После добавления нового товара

Выбран новый ряд элементов

Выбранная строка элемента привязки данных

Чтобы упростить задачу, я делюсь кодом xaml, как показано ниже.

<UserControl.Resources>
        <ResourceDictionary>

            <Style TargetType = "TabItem">
                <Setter Property = "Header" Value = "{Binding DataContext.SelectedTreeItem.Name, Mode=OneWay}"></Setter>
            </Style>
            <Style TargetType = "DataGridCell">
                <Setter Property = "BorderBrush" Value = "Gainsboro"></Setter>
                <Setter Property = "BorderThickness" Value = "0"></Setter>
            </Style>
            <Style TargetType = "DataGridRow">
                <Style.Triggers>

                    <Trigger Property = "ItemsControl.AlternationIndex" Value = "0">
                        <Setter Property = "Background" Value = "{StaticResource ContentBackgroundColorBrush}"/>
                    </Trigger>
                    <Trigger Property = "ItemsControl.AlternationIndex" Value = "1">
                        <Setter Property = "Background" Value = "White"/>
                    </Trigger>
                    <Trigger Property = "IsSelected" Value = "True">
                        <Setter Property = "Foreground" Value = "DarkBlue"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ResourceDictionary>
    </UserControl.Resources>
    <AdornerDecorator>
        <Grid>
            <DataGrid  x:Name = "OperationClassDataGrid"
                       ItemsSource = "{Binding PlantMachine.OperationClasses, UpdateSourceTrigger=PropertyChanged}"                     
                       AlternationCount = "2"
                       CanUserAddRows = "True"
                       CanUserDeleteRows = "True"
                       CanUserReorderColumns = "False"
                       CanUserResizeColumns = "False"
                       CanUserSortColumns = "False"
                       AutoGenerateColumns = "False" 
                       IsReadOnly = "False">
                <DataGrid.Columns>
                    <DataGridTextColumn Visibility = "Hidden" Header = "{DynamicResource Plant.OperationClass.List.Header.Key}" Binding = "{Binding OperationKey}" Width = "Auto" SortDirection = "Ascending"/>
                    <DataGridTemplateColumn Header = "{DynamicResource Plant.OperationClass.List.Header.Name}">
                        <DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate DataType = "{x:Type model:OperationClass}">
                                <TextBlock Text = "{Binding OperationName}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellEditingTemplate>

                        <!-- Instead of defining the CellTemplate explicitly, 
           we assign the CellTemplateSelector instead -->
                        <DataGridTemplateColumn.CellTemplateSelector>
                            <local:OperationClassTemplateSelector>
                                <local:OperationClassTemplateSelector.DefaultTemplate>
                                    <DataTemplate DataType = "{x:Type model:OperationClass}">
                                        <TextBox Text = "{Binding OperationName}" />
                                    </DataTemplate>
                                </local:OperationClassTemplateSelector.DefaultTemplate>
                                <local:OperationClassTemplateSelector.PlaceholderTemplate>
                                    <DataTemplate>
                                        <TextBlock Text = "new operation class..." />
                                    </DataTemplate>
                                </local:OperationClassTemplateSelector.PlaceholderTemplate>
                            </local:OperationClassTemplateSelector>
                        </DataGridTemplateColumn.CellTemplateSelector>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Header = "{DynamicResource Plant.OperationClass.List.Header.Start}" Binding = "{Binding RangeStartValue}" Width = "Auto" SortDirection = "Ascending"/>
                    <DataGridTextColumn Header = "{DynamicResource Plant.OperationClass.List.Header.End}" Binding = "{Binding RangeEndValue}" Width = "Auto" SortDirection = "Ascending"/>
                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Image Source = "/Resources/Images/Delete.png"  Width = "125" Height = "30" HorizontalAlignment = "Right">
                                    <Image.InputBindings>
                                        <MouseBinding  Gesture = "LeftClick" CommandParameter = "{Binding Path=Key}"  Command = "{Binding DataContext.RemoveOperationClassCommand, RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type DataGrid}}}"    />
                                    </Image.InputBindings>
                                </Image>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
        </AdornerDecorator>
</UserControl>

Другие вопросы по теме