Я знаю, что этот вопрос дублирует несколько других, потому что я изучал эти «несколько других». И я не смог понять, где я напортачил.
Этот пост конкретно о:
- C#
- WPF
- DataGrid
- List <>
- Привязка DataGrid к списку <>
Когда я запускаю свой код, DataGrid позволяет мне изменять и удалять строки. DataGrid не позволяет мне добавлять строку. Почему?
Xaml:
<Window
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:myNamespace"
xmlns:Schema="clr-namespace:System.Xml.Schema;assembly=System.Xml.ReaderWriter" x:Class="myNamespace.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="600">
<Grid>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="col_id" Width="200" Header="Col ID" Binding="{Binding value_id}" />
<DataGridTextColumn x:Name="col_1" Width="200" Header="Col One" Binding="{Binding value_1}" />
<DataGridTextColumn x:Name="col_2" Width="200" Header="Col Two" Binding="{Binding value_2}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
Код позади:
using System.Collections.Generic;
using System.Windows;
namespace myNamespace
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
init_item_list();
dataGrid.ItemsSource = ItemList;
}
public List<DataItem> ItemList = new List<DataItem>();
public void init_item_list()
{
ItemList.Add(new DataItem(1, "one", "i"));
ItemList.Add(new DataItem(2, "two", "ii"));
ItemList.Add(new DataItem(3, "three", "ii"));
}
public class DataItem
{
public DataItem(int id, string val_1, string val_2)
{
value_id = id;
value_1 = val_1;
value_2 = val_2;
}
private int _value_id;
public int value_id
{
get { return _value_id; }
set { _value_id = value; }
}
private string _value_1;
public string value_1
{
get { return _value_1; }
set { _value_1 = value; }
}
private string _value_2;
public string value_2
{
get { return _value_2; }
set { _value_2 = value; }
}
}
}
}
Мне кажется, я видел строки, добавленные из пользовательского интерфейса, когда DataGrid привязан к списку. Однако я не вижу, чтобы он работал с моим кодом здесь.
Эфраим Ньюман прокомментировал, что проблема может заключаться в использовании List. В других сообщениях я видел упоминание о том, что ObservableCollection работает лучше, чем List for DataGrid.
В коде позади я изменил
public List<DataItem> ItemList = new List<DataItem>();
на
public ObservableCollection<DataItem> ItemList = new ObservableCollection<DataItem>();
раньше изменение (с помощью List), работающая DataGrid выглядела так:
![Before](https://i.stack.imgur.com/UVpPJ.png)
After the change (using ObservableCollection), the running DataGrid looked like this:
введите описание изображения здесь
В любом случае нет пустой строки для добавления новой записи.
Я не вижу никакой разницы при использовании ObservableCollection вместо List. DataGrid по-прежнему не позволяет мне добавить запись.
Я думаю, что преимущество использования ObservableCollection заключается в том, что ObservableCollection уведомляет (вызывает DataGrid) для обновления всякий раз, когда в ObservableCollection есть изменения. Кажется, это не проблема.
Здесь проблема в том, что DataGrid не принимает никаких новых записей.
В Xaml я попытался явно установить для CanUserAddRows значение True и даже False.
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" CanUserAddRows="True" >
Ответ
@ mm8 обнаружил мою проблему: мне нужно было добавить конструктор по умолчанию без параметров. Я добавил:
public DataItem() { }
Xaml остается таким, каким был изначально. Обратите внимание, что теперь я привязываюсь к List .
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace myNamespace
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
init_item_list();
dataGrid.ItemsSource = _itemList;
}
private List<DataItem> _itemList = new List<DataItem>();
public List<DataItem> ItemList
{
get { return _itemList; }
set { _itemList = value; }
}
public void init_item_list()
{
_itemList.Add(new DataItem(1, "one", "i"));
_itemList.Add(new DataItem(2, "two", "ii"));
_itemList.Add(new DataItem(3, "three", "ii"));
}
public class DataItem
{
public DataItem() { }
public DataItem(int id, string val_1, string val_2)
{
value_id = id;
value_1 = val_1;
value_2 = val_2;
}
private int _value_id;
public int value_id
{
get { return _value_id; }
set { _value_id = value; }
}
private string _value_1;
public string value_1
{
get { return _value_1; }
set { _value_1 = value; }
}
private string _value_2;
public string value_2
{
get { return _value_2; }
set { _value_2 = value; }
}
}
Я думаю, что в примере, где вы не можете использовать List, вы измените List напрямую и вам понадобится DataGrid для отображения изменения.
Я тестировал этот код, используя как List, так и ObservableCollection. Теперь он работает с добавлением конструктора по умолчанию без параметров.