Невозможно создать новые строки вручную в DataGrid со столбцами типа DataGridTemplateColumn - PullRequest
0 голосов
/ 15 октября 2019

Сводка

В моем приложении у меня есть WPF DataGrid с несколькими DataGridTemplateColumns. По какой-то причине пользователь не может вручную добавить строки в DataGrid, нажав клавишу Enter. У меня есть другие DataGrids, где есть только DataGridTextcolumns. В этой DataGrid пользователь может добавлять новые строки, нажимая клавишу Enter.

Описание

Я могу воспроизвести проблему с небольшим приложением с тремя DataGrids.

ПервыйDataGrid содержит только DataGridTextColumn. Если я щелкну начальную строку в столбце, я могу напечатать что-нибудь в столбце и нажать клавишу ввода. Это автоматически создаст новую строку, и моя коллекция ObservableCollection будет автоматически обновлена, содержащая 1 элемент для строки, которую я только что создал. Так что, похоже, это работает как ожидалось.

Второй DataGrid содержит только DataGridTemplateColumn со Slider. Но с этой DataGrid я не могу добавить новую строку в качестве первой. Я просто хочу установить значение ползунка и нажать клавишу Enter. Затем я хочу новую строку с другим ползунком в DataGrid.

В моем третьем DataGrid я объединил две сетки с DataGridTextColumn и DataGridTemplateColumn с той же настройкой. В этой DataGrid я могу добавить новую строку только в том случае, если я нажму клавишу Enter в DataGridTextColumn.

Code

Ниже представлен воспроизводимый код. Просто создайте новое приложение WPF под названием WpfApp1 в VS и скопируйте вставку в MainWindow.xaml и MainWindow.xaml.cs.

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>

    <StackPanel Orientation="Vertical">

        <Label Content="Can create a new row manually in the grid by hitting enter in the 'Text' column" Margin="0,20,0,0" />
        <DataGrid ItemsSource="{Binding Models1}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False">
            <DataGrid.Columns>

                <DataGridTextColumn Binding="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Text" Width="300" />

            </DataGrid.Columns>
        </DataGrid>

        <Button Content="Summary" Height="40" Click="Button_Click" Margin="0,20,0,20" />

        <Label Content="Can't create a new row manually in the grid by hitting enter" />
        <DataGrid ItemsSource="{Binding Models2}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False">
            <DataGrid.Columns>

                <DataGridTemplateColumn Header="Number" Width="300">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>

                            <Slider Value="{Binding Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="1" Maximum="300" />

                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

            </DataGrid.Columns>
        </DataGrid>

        <Label Content="Can create a new row manually in the grid by hitting enter in the 'Text' column" Margin="0,80,0,0" />
        <DataGrid ItemsSource="{Binding Models3}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False">
            <DataGrid.Columns>

                <DataGridTextColumn Binding="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Text" Width="100" />

                <DataGridTemplateColumn Header="Number" Width="300">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>

                            <Slider Value="{Binding Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="1" Maximum="300" />

                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>



            </DataGrid.Columns>
        </DataGrid>

    </StackPanel>
</Window>

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Linq;

using System.Windows;


namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var vm = DataContext as ViewModel;
            var t1 = $"All text: {string.Join(", ", vm.Models1.Select(r => r.Text))}";
            var t2 = $"All numbers: {string.Join(", ", vm.Models2.Select(r => r.Number))}";
            var t3 = $"All numbers: {string.Join(", ", vm.Models3.Select(r => r.Number))}";
            MessageBox.Show($"Summary: {Environment.NewLine} {t1} {Environment.NewLine} {t2} {Environment.NewLine} {t3}");
        }
    }

    class Model : INotifyPropertyChanged
    {
        string text;
        double number;

        public event PropertyChangedEventHandler PropertyChanged;

        public Model()
        {
            Console.WriteLine("");
        }

        public string Text
        {
            get { return text; }
            set
            {
                if (value != text)
                {
                    text = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
                }
            }
        }

        public double Number
        {
            get { return number; }
            set
            {
                if (value != number)
                {
                    number = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Number)));
                }
            }
        }
    }

    class ViewModel
    {
        public ObservableCollection<Model> Models1 { get; private set; }
        public ObservableCollection<Model> Models2 { get; private set; }
        public ObservableCollection<Model> Models3 { get; private set; }

        public ViewModel()
        {
            Models1 = new ObservableCollection<Model>();
            Models2 = new ObservableCollection<Model>();
            Models3 = new ObservableCollection<Model>();
        }

    }
}


Другое

Я подозреваю, что DataGridTemploateColumn имеет другойповедение затем DataGridTextColumn. Это было бы полезно знать в будущем. Но проблема все еще существует.

Проблема проста: как вручную добавить новую строку в DataGrid, где есть один или несколько DataGridTemplateColumns?

Я нашел этот пост (Невозможно вставить строки в Datagrid с использованием DataGridTemplateColumn ) с более или менее такой же проблемой. Рекомендация состояла в том, чтобы изменить CellTemplate DataGridTemplateColumn на CellEditingTemplate. Но, похоже, это не решило мою проблему.

Ответы [ 2 ]

0 голосов
/ 16 октября 2019

Спасибо, мм8!

Однако мне не удалось найти удовлетворительное решение проблемы. У меня есть кнопка, NummerUpDown и DatePicker в каждой строке, и эти элементы управления, кажется, не работают так хорошо.

Когда я загружаю свою программу, в DataGrid всегда есть строка по умолчанию (из-засвойство CanUserAddRow = true) . Для этой строки конструктор модели не был вызван. Так что все привязки не будут работать. Элементы управления NummericUpDown имеют значения по умолчанию, которые я установил в конструкторе модели. Эти значения не отображаются в строке по умолчанию. Свойство кнопки (также в строке по умолчанию) ICommand не будет вызывать ее обратный вызов. Они будут работать только в том случае, если для строки по умолчанию вызывается конструктор модели. Поэтому, если я программно создаю новую модель для ItemSrid ItemSrid, при запуске будет две строки в DataGrid: строка, которую я создал, где работают все привязки. Строка по умолчанию, где привязки не работают.

В настоящее время я не могу заставить это работать ...: (

0 голосов
/ 15 октября 2019

Вы можете вызвать BeginEdit() для вставки новой строки, например, обработав KeyDown из Slider:

private void OnKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
        dg.BeginEdit();
}

XAML:

<Slider Value="{Binding Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="1" Maximum="300"
        KeyDown="OnKeyDown"/>

Вы также можете обернуть эту функцию в пользовательский класс DataGridTemplateColumn:

public class CustomTemplateColumn : DataGridTemplateColumn
{
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        FrameworkElement fe = base.GenerateElement(cell, dataItem);
        if (fe != null)
            fe.KeyDown += OnKeyDown;
        return fe;
    }

    private void OnKeyDown(object sender, KeyEventArgs e)
    {
        DataGridOwner.BeginEdit();
    }
}

XAML:

<local:CustomTemplateColumn Header="Number" Width="300">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>

            <Slider Value="{Binding Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="1" Maximum="300" />

        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</local:CustomTemplateColumn>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...