C# 在WPF中动态生成其他DataGrid列

C# 在WPF中动态生成其他DataGrid列,c#,wpf,xaml,datagrid,C#,Wpf,Xaml,Datagrid,我有一个带有2个静态列(名称和年龄)的DataGrid。我希望能够向我的DataGrid动态添加可变数量的附加列,因为我事先不知道会有多少附加列。我还希望生成的DataGrid是可编辑的 我已经创建了一个“MyData”类,我想将其用于我的DataGrid DataContext(作为MyData对象的可观察集合) 请参见下面AddNewColumnsAndData()方法的实现: public void AddNewColumnsAndData(List<string> count

我有一个带有2个静态列(名称和年龄)的DataGrid。我希望能够向我的DataGrid动态添加可变数量的附加列,因为我事先不知道会有多少附加列。我还希望生成的DataGrid是可编辑的

我已经创建了一个“MyData”类,我想将其用于我的DataGrid DataContext(作为MyData对象的可观察集合)

请参见下面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;

    }
public void addnewcolumns和data(列出国家名称、数据网格dgr)
{
foreach(countryname中的字符串countryname)
{
Binding bdg=new Binding();//不确定绑定构造函数中应该包含什么适当的参数
bdg.NotifyOnTargetUpdated=true;
bdg.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
bdg.Mode=BindingMode.TwoWay;//不确定是否应该设置其他bdg属性
DataGridTextColumn newCityCol=新DataGridTextColumn();
newCityCol.Header=countryname;
newCityCol.Binding=bdg;
dgr.Columns.Add(newCityCol);
};
List mycitylist 1=新列表(){“巴黎”、“内罗毕”、“东京”};
List mycitylist 2=新列表(){“斯特拉斯堡”、“蒙巴萨”、“京都”};
MyData firstrow=新的MyData
{
NameCol=“约翰”,
AgeCol=“45”,
CityColList=mycitylist 1
};
MyData secondrow=新的MyData
{
NameCol=“玛丽”,
AgeCol=“34”,
CityColList=myCityList2
};
ObservableCollection datacollection=新的ObservableCollection();
datacollection.Add(第一行);
datacollection.Add(第二行);
dgr.DataContext=数据收集;
}
带有两个静态列“Name”和“Age”的my DataGrid的XAML:

<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'的异常”:双向绑定需要路径或XPath 这说明我需要更改设置绑定属性的方式

当我注释掉'bdg.Mode=BindingMode.TwoWay;'行,程序运行正常,但是,我无法编辑DataGrid,也不能编辑国家标题下的城市名称,而是粘贴MyNameSpace.MyData

我的问题是:如何适当地设置绑定,以便单元格正确显示城市名称,以及如何使生成的DataGrid可编辑

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 NameCol}
这是因为
Binding
继承自
MarkupExtension
。您可以编写自己的
MarkupExtension
子类。例如,它是编写具有强类型常量参数的值转换器的一种非常方便的方法

您可以使用默认构造函数,并分别设置
Path

{Binding Path=NameCol}
这就是为什么你不能这样做:

{Binding Mode=TwoWay, NameCol}
…因为未命名的“参数”和命名的“参数”不同。构造函数参数优先,属性初始化(如果有)紧随其后

这与此相同,但会设置一些属性:

{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}

这是一个有趣的语法

谢谢@Ed Plukett。请注意,所有列都应该是可编辑的(即非只读)。问题,为什么要注释掉//bdg.NotifyOnTargetUpdated=true?此外,上述方法在大部分情况下都有效。我唯一的问题是,当我为“动态”添加的列编辑DataGrid时,我似乎看不到我的编辑。是否有我可能缺少的绑定属性?@Nodame你在哪里处理TargetUpdated事件?@Nodame我刚粘贴到你的循环版本中,它工作了。但是“看我的编辑”是不精确的;你希望在哪里看到他们?我在调试器中看到它们<但是,代码>列表在替换项目时不会引发任何事件,因此如果要将其他内容绑定到集合,则需要对
城市列表
使用
可观察集合
{Binding Path=NameCol}
{Binding Mode=TwoWay, NameCol}
{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}