只是不得不尝试这个,奇怪但有趣的问题:-)设法通过使用以下内容使其工作。
抱歉回答太长,可能要详细一点:-)
首先,数据网格。干净利落
<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; }
创建一些虚拟数据来填充列表并在 DataGrid 上设置 ItemsSource
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;
为 FileName 属性添加了 DataGridTextColumn
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 提供给 Converter 的构造函数,以便它知道要查找哪个属性。
最后是转换器
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;
}
}
在 Convert 中,它将检查给定的 MyPropertyName,如果找到,则返回 MyPropertyValue,否则返回 null。 ConvertBack 方法也是如此,但它会将 MyPropertyValue 设置为具有给定 MyPropertyName 的 MyProperty 的新值,然后返回列表(列表或 null)。
不在 MyFile 列表中的属性将不可编辑,它们只会在离开单元格时变回 null(这可能就是重点)。
这将产生如下所示的 DataGrid。