Просто нужно было попробовать эту странную, но забавную проблему :-) Удалось заставить ее работать, используя следующее.Извините за длинный ответ, вероятно, способ подробно :-)
Прежде всего, DataGrid.Простой и простой
<DataGrid Name="c_dataGrid" AutoGenerateColumns="False"
CanUserAddRows="False" CanUserDeleteRows="False"/>
Затем класс File с именем MyFile
public class MyFile
{
public MyFile() : this(string.Empty) {}
public MyFile(string fileName)
{
FileName = fileName;
MyPropertyList = new ObservableCollection<MyProperty>();
}
public string FileName
{
set;
get;
}
public ObservableCollection<MyProperty> MyPropertyList
{
get;
set;
}
}
Класс свойства с именем MyProperty
public class MyProperty
{
public MyProperty() : this(string.Empty, string.Empty) {}
public MyProperty(string propertyName, string propertyValue)
{
MyPropertyName = propertyName;
MyPropertyValue = propertyValue;
}
public string MyPropertyName
{
set;
get;
}
public string MyPropertyValue
{
set;
get;
}
}
Список, содержащий MyFiles
public ObservableCollection<MyFile> MyFileList{ get; set; }
Созданы некоторые фиктивные данные для заполнения списка и установки ItemsSource в DataGrid
MyFile myFile1 = new MyFile("MyFile1");
myFile1.MyPropertyList.Add(new MyProperty("Name1", "Value1"));
myFile1.MyPropertyList.Add(new MyProperty("Name2", "Value2"));
myFile1.MyPropertyList.Add(new MyProperty("Name3", "Value3"));
MyFile myFile2 = new MyFile("MyFile2");
myFile2.MyPropertyList.Add(new MyProperty("Name1", "Value1"));
myFile2.MyPropertyList.Add(new MyProperty("Name4", "Value4"));
myFile2.MyPropertyList.Add(new MyProperty("Name5", "Value5"));
MyFileList = new ObservableCollection<MyFile>();
MyFileList.Add(myFile1);
MyFileList.Add(myFile2);
c_dataGrid.ItemsSource = MyFileList;
Добавлен DataGridTextColumn для атрибута FileName
c_dataGrid.Columns.Add(GetNewMyFileNameColumn());
private DataGridColumn GetNewMyFileNameColumn()
{
DataGridTextColumn myFileNameColumn = new DataGridTextColumn();
myFileNameColumn.Header = "FileName";
myFileNameColumn.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);
Binding valueBinding = new Binding();
valueBinding.Path = new PropertyPath("FileName");
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
valueBinding.NotifyOnSourceUpdated = true;
valueBinding.NotifyOnTargetUpdated = true;
myFileNameColumn.Binding = valueBinding;
return myFileNameColumn;
}
А затем для MyPropertyList,Я хотел добавить каждое MyPropertyName только один раз, поэтому, если у меня есть следующее
MyFile1
-Name1
-Name2
-Name3
MyFile2
-Name1
-Name4
-Name5
сгенерированные столбцы должны быть Name1, Name2, Name3, Name4 и Name5.
foreach (MyFile myFile in MyFileList)
{
foreach (MyProperty myProperty in myFile.MyPropertyList)
{
if (ColumnAlreadyAdded(myProperty.MyPropertyName) == false)
{
c_dataGrid.Columns.Add(GetNewMyPropertyColumn(myProperty.MyPropertyName));
}
}
}
private bool ColumnAlreadyAdded(string myPropertyName)
{
foreach (DataGridColumn dataGridColumn in c_dataGrid.Columns)
{
if (dataGridColumn.Header.ToString() == myPropertyName)
{
return true;
}
}
return false;
}
private DataGridColumn GetNewMyPropertyColumn(string myPropertyName)
{
DataGridTextColumn myFileNameColumn = new DataGridTextColumn();
myFileNameColumn.Header = myPropertyName;
myFileNameColumn.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);
Binding valueBinding = new Binding();
valueBinding.Path = new PropertyPath("MyPropertyList");
valueBinding.Converter = new MyPropertyConverter(myPropertyName);
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
valueBinding.NotifyOnSourceUpdated = true;
valueBinding.NotifyOnTargetUpdated = true;
myFileNameColumn.Binding = valueBinding;
return myFileNameColumn;
}
Мне пришлось передать MyPropertyName в конструктор конвертера, чтобы он знал, какое свойство искать.
И, наконец, конвертер
public class MyPropertyConverter : IValueConverter
{
private string m_propertyName = string.Empty;
ObservableCollection<MyProperty> m_myPropertyList = null;
public MyPropertyConverter(string propertyName)
{
m_propertyName = propertyName;
}
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
m_myPropertyList = value as ObservableCollection<MyProperty>;
if (m_myPropertyList == null)
{
return null;
}
foreach (MyProperty myProperty in m_myPropertyList)
{
if (myProperty.MyPropertyName == m_propertyName)
{
return myProperty.MyPropertyValue;
}
}
return null;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (m_myPropertyList != null)
{
foreach (MyProperty myProperty in m_myPropertyList)
{
if (myProperty.MyPropertyName == m_propertyName)
{
myProperty.MyPropertyValue = value.ToString();
break;
}
}
}
return m_myPropertyList;
}
}
In Преобразовать егопроверит указанное имя MyPropertyName и, если оно его найдет, вернет MyPropertyValue, в противном случае - ноль.То же самое относится и к методу ConvertBack, но он установит для MyPropertyValue новое значение для MyProperty с заданным MyPropertyName, а затем вернет список, являющийся либо списком, либо нулевым.
Свойства, которых нет вСписок MyFile не будет редактироваться, он просто изменится на ноль при выходе из ячейки (что, вероятно, является точкой).
Это приведет к созданию DataGrid, который выглядит следующим образом.
