我有一个带有2个静态列(名称和年龄)的DataGrid。我希望能够动态地向我的DataGrid添加可变数量的附加列,因为我事先不知道将有多少额外的列。我还希望结果DataGrid可以编辑。
我创建了一个'MyData'类,我想用它作为我的DataGrid DataContext(作为MyData Objects的ObservableCollection)。
public class MyData
{
public string NameCol { get; set; }
public string AgeCol { get; set; }
public List<string> CitiesList { get; set; }
}
我要添加的动态列标题是'Country1','Country2',...,'CountryN'。这些列中的每个条目都是这些国家的城市。
我有一个方法,将countryNames列表和我的DataGrid作为参数。为了便于说明,我正在传递:
List<string> CountryNames = new List<string>() {"France", "Kenya", "Japan"};
我正在打电话:
AddNewColumnsAndData(CountryNames, this.dgr);
请参阅下面的AddNewColumnsAndData()方法的实现:
public void AddNewColumnsAndData(List<string> countryNames, DataGrid dgr)
{
foreach (string countryname in countryNames)
{
Binding bdg = new Binding(); //Not sure what appropriate argument should go in the Binding Constructor
bdg.NotifyOnTargetUpdated = true;
bdg.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
bdg.Mode = BindingMode.TwoWay;//Not sure if there are other bdg Properties I should be setting
DataGridTextColumn newCityCol = new DataGridTextColumn();
newCityCol.Header = countryname;
newCityCol.Binding = bdg;
dgr.Columns.Add(newCityCol);
};
List<string> myCityList1 = new List<string>() {"Paris", "Nairobi", "Tokyo"};
List<string> myCityList2 = new List<string>() { "Strasbourg", "Mombasa", "Kyoto" };
MyData firstrow = new MyData
{
NameCol = "John",
AgeCol = "45",
CityColList = myCityList1
};
MyData secondrow = new MyData
{
NameCol = "Mary",
AgeCol = "34",
CityColList = myCityList2
};
ObservableCollection<MyData> datacollection = new ObservableCollection<MyData>();
datacollection.Add(firstrow);
datacollection.Add(secondrow);
dgr.DataContext = datacollection;
}
我的DataGrid的XAML,带有两个静态列'Name'和'Age':
<DataGrid x:Name="dgr" ItemsSource="{Binding}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<DataGridTextColumn Header="Age" Binding="{Binding AgeCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</DataGrid.Columns>
</DataGrid>
不幸的是,这不太合适。我收到此错误:“类型'System.InvalidOperationException'的异常:双向绑定需要Path或XPath。” 这告诉我,我需要改变我设置绑定属性的方式。
当我注释掉'bdg.Mode = BindingMode.TwoWay;'时行,该程序运行正常,但是,我无法编辑DataGrid,而不是国家标题下面的城市名称,它被粘贴MyNameSpace.MyData。
我的问题是:如何正确设置绑定,以便单元格正确显示城市名称,以及如何使我生成的DataGrid可编辑?
答案 0 :(得分:0)
int citiesListIndex = 0;
foreach (string countryname in countryNames)
{
// This is the Path. You're binding to CitiesList[0]
// CitiesList[1], etc.
string propertyPath = $"CitiesList[{citiesListIndex}]";
// Pass path to constructor.
Binding bdg = new Binding(propertyPath);
// No-op
//bdg.NotifyOnTargetUpdated = true;
// Is this a read-only column? If it's read-only, this is a no-op
bdg.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
// Is this a read-only column? If it's read-only, this is a no-op
bdg.Mode = BindingMode.TwoWay;
DataGridTextColumn newCityCol = new DataGridTextColumn();
newCityCol.Header = countryname;
newCityCol.Binding = bdg;
dgr.Columns.Add(newCityCol);
++citiesListIndex;
}
这就是它的原因。
这是XAML中的绑定
Binding="{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
NameCol
是Path
属性。在XAML中,它使用一个参数调用Binding(String path)
构造函数:
{Binding NameCol}
这是有效的,因为Binding
继承自MarkupExtension
。您可以编写自己的MarkupExtension
子类。例如,用强类型常量参数编写值转换器是一种非常方便的方法。
您可以使用默认构造函数,并单独设置Path
:
{Binding Path=NameCol}
这就是你不能这样做的原因:
{Binding Mode=TwoWay, NameCol}
...因为未命名的“参数”和命名的“参数”是不同的。首先是构造函数参数,然后是属性初始化(如果有)。
这样做相同,但随后设置了一些属性:
{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}
这是一个有趣的语法。