以编程方式将列添加到不编译的数据网格
Programmatically add columns to datagrid not compiling
这是
的延续
我看过这个post:
How to add Data to a WPF datagrid programatically
数据网格就是这样:
<DataGrid Name="dtgResults" Background="Transparent" AutoGenerateColumns="False"/>
其中一切似乎都运行良好,但是当我将它放入我的解决方案时它无法编译:
谁能解释一下为什么?
---编辑---
我现在意识到我误解了上面 link 中的内容。
简而言之,我有一个绑定到可观察集合的数据网格。
我必须再添加两列。怎么办?
---EDIT2---- 用于 CBreeze
dtgResults.ItemsSource = obcmMyDim;<--------previous data here
DataGridTextColumn textColumn1 = new DataGridTextColumn();
textColumn1.Header = "AAA1";
textColumn1.Binding = new Binding("AAA1");
DataGridTextColumn textColumn2 = new DataGridTextColumn();
textColumn2.Header = "AAA2";
textColumn2.Binding = new Binding("AAA2");
Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() => dtgResults.Columns.Add(textColumn1)));
Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() => dtgResults.Columns.Add(textColumn2)));
dtgResults.Items.Add(new { AAA1 = "Col1Row1", AAA2 = "Col2Row1"});
dtgResults.Items.Add(new { AAA1 = "Col1Row2", AAA2 = "Col2Row2" });
---编辑 3--- 为 JH
所以简而言之,我有一个绑定到数据网格的可观察集合,输出如下:
然后我用你的方法添加列:
var names = obcmMyDim.First().obcItemsName; // All entries must have the same list of obcItemsName and in the same order
for (int i = 0; i < names.Count; i++)
{
DataGridTextColumn c = new DataGridTextColumn();
c.Header = names[i];
var b = new Binding();
string str = string.Format("obcmMyDim.obcItemsMeasured[{0}]", i);
b.Path = new PropertyPath(str);
b.Mode = BindingMode.TwoWay;
c.Binding = b;
dtgResults.Columns.Add(c);
}
至于绑定数组
并且绑定 str 是 "obcmMyDim.obcItemsMeasured[0]" ...1....n
但我得到的是列在那里,但它们是空的
它没有编译,因为你使用了ItemCollection
。我认为您没有像 link 的回答那样创建自己的 class 并使用了 System.Windows.Controls.ItemCollection
,在这种情况下不能使用。
你试过类似的东西吗?
dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.1"});
dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.2"});
编辑:
for (int i = 1; i <= 10; i++)
{
dtgResults.Items.Add(new { a.1 = "Test" + i, a.2 = "Test" + i});
}
您可以绑定到一个数组中的项目,但您必须确保所有数组都相同(相同的字段,相同的顺序,以便它们的索引一致)。这是一个基于您遇到的其他问题的示例。
请注意,必须将字段 obcItemsMeasured 更改为 属性,因为绑定需要属性(而不是字段)。
XAML:
<Window x:Class="WpfApplication2.MainWindow"
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:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DataGrid x:Name="dtgResults" CanUserAddRows="False" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding NameAxisDimension}" Header="NameAxisDimension" />
<DataGridTextColumn Binding="{Binding Nominal}" Header="Nominal" />
<DataGridTextColumn Binding="{Binding UpperTolerance}" Header="UpperTolerance" />
<DataGridTextColumn Binding="{Binding LowerTolerance}" Header="LowerTolerance" />
</DataGrid.Columns>
</DataGrid>
</Window>
代码:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Build list of MyDimensions manually (since I don't have access to your data)
var obcmMyDim = new ObservableCollection<MyDimension>(CreateData());
dtgResults.ItemsSource = obcmMyDim;
var names = obcmMyDim.First().obcItemsName; // All entries must have the same list of obcItemsName and in the same order
for (int i=0; i<names.Count; i++)
{
DataGridTextColumn c = new DataGridTextColumn();
c.Header = names[i];
var b = new Binding();
b.Path = new PropertyPath(string.Format("obcItemsMeasured[{0}]", i)); // Binding is based on index into array, thats why all entries have to have the same dynamic fields
b.Mode = BindingMode.TwoWay;
c.Binding = b;
dtgResults.Columns.Add(c);
}
}
public IList<MyDimension> CreateData()
{
List<MyDimension> Dimensions = new List<MyDimension>();
string[] names = new string[] { "PART11", "PART20" }; // They must all have the same obcItemsName/obcItemsMeasured entries, and in the same order
Dimensions.Add(CreateItem("LOC1-X", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-Y", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-D", names, 10.0, 10.1));
Dimensions.Add(CreateItem("LOC1-RN", names, 0, 0));
Dimensions.Add(CreateItem("LOC2-X", names, 0, 0));
Dimensions.Add(CreateItem("LOC2-Y", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-DF", names, 10.2, 10.3));
Dimensions.Add(CreateItem("LOC2-TP", names, 0, 0));
Dimensions.Add(CreateItem("DIST1-M", names, 14.14214, 14.14215));
Dimensions.Add(CreateItem("DIST2-M", names, 10.4, 10.5));
// etc...
return Dimensions;
}
public MyDimension CreateItem(string name, string[] names, params double[] values)
{
var d = new MyDimension();
d.NameAxisDimension = name;
for (int i = 0; i < names.Length; i++)
{
d.obcItemsName.Add(names[i]);
d.obcItemsMeasured.Add(values[i]);
}
return d;
}
}
public class MyDimension
{
public MyDimension()
{
obcItemsName = new ObservableCollection<string>();
obcItemsMeasured = new ObservableCollection<double>();
}
public string NameAxisDimension { get; set; }
public double Nominal { get; set; }
public double UpperTolerance { get; set; }
public double LowerTolerance { get; set; }
public ObservableCollection<string> obcItemsName;
public ObservableCollection<double> obcItemsMeasured { get; set; } // Has to be a property since it is used in the binding
}
}
截图:
这是
的延续我看过这个post:
How to add Data to a WPF datagrid programatically
数据网格就是这样:
<DataGrid Name="dtgResults" Background="Transparent" AutoGenerateColumns="False"/>
其中一切似乎都运行良好,但是当我将它放入我的解决方案时它无法编译:
谁能解释一下为什么?
---编辑---
我现在意识到我误解了上面 link 中的内容。 简而言之,我有一个绑定到可观察集合的数据网格。 我必须再添加两列。怎么办?
---EDIT2---- 用于 CBreeze
dtgResults.ItemsSource = obcmMyDim;<--------previous data here
DataGridTextColumn textColumn1 = new DataGridTextColumn();
textColumn1.Header = "AAA1";
textColumn1.Binding = new Binding("AAA1");
DataGridTextColumn textColumn2 = new DataGridTextColumn();
textColumn2.Header = "AAA2";
textColumn2.Binding = new Binding("AAA2");
Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() => dtgResults.Columns.Add(textColumn1)));
Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() => dtgResults.Columns.Add(textColumn2)));
dtgResults.Items.Add(new { AAA1 = "Col1Row1", AAA2 = "Col2Row1"});
dtgResults.Items.Add(new { AAA1 = "Col1Row2", AAA2 = "Col2Row2" });
---编辑 3--- 为 JH 所以简而言之,我有一个绑定到数据网格的可观察集合,输出如下:
然后我用你的方法添加列:
var names = obcmMyDim.First().obcItemsName; // All entries must have the same list of obcItemsName and in the same order
for (int i = 0; i < names.Count; i++)
{
DataGridTextColumn c = new DataGridTextColumn();
c.Header = names[i];
var b = new Binding();
string str = string.Format("obcmMyDim.obcItemsMeasured[{0}]", i);
b.Path = new PropertyPath(str);
b.Mode = BindingMode.TwoWay;
c.Binding = b;
dtgResults.Columns.Add(c);
}
至于绑定数组
并且绑定 str 是 "obcmMyDim.obcItemsMeasured[0]" ...1....n
但我得到的是列在那里,但它们是空的
它没有编译,因为你使用了ItemCollection
。我认为您没有像 link 的回答那样创建自己的 class 并使用了 System.Windows.Controls.ItemCollection
,在这种情况下不能使用。
你试过类似的东西吗?
dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.1"});
dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.2"});
编辑:
for (int i = 1; i <= 10; i++)
{
dtgResults.Items.Add(new { a.1 = "Test" + i, a.2 = "Test" + i});
}
您可以绑定到一个数组中的项目,但您必须确保所有数组都相同(相同的字段,相同的顺序,以便它们的索引一致)。这是一个基于您遇到的其他问题的示例。
请注意,必须将字段 obcItemsMeasured 更改为 属性,因为绑定需要属性(而不是字段)。
XAML:
<Window x:Class="WpfApplication2.MainWindow"
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:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DataGrid x:Name="dtgResults" CanUserAddRows="False" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding NameAxisDimension}" Header="NameAxisDimension" />
<DataGridTextColumn Binding="{Binding Nominal}" Header="Nominal" />
<DataGridTextColumn Binding="{Binding UpperTolerance}" Header="UpperTolerance" />
<DataGridTextColumn Binding="{Binding LowerTolerance}" Header="LowerTolerance" />
</DataGrid.Columns>
</DataGrid>
</Window>
代码:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Build list of MyDimensions manually (since I don't have access to your data)
var obcmMyDim = new ObservableCollection<MyDimension>(CreateData());
dtgResults.ItemsSource = obcmMyDim;
var names = obcmMyDim.First().obcItemsName; // All entries must have the same list of obcItemsName and in the same order
for (int i=0; i<names.Count; i++)
{
DataGridTextColumn c = new DataGridTextColumn();
c.Header = names[i];
var b = new Binding();
b.Path = new PropertyPath(string.Format("obcItemsMeasured[{0}]", i)); // Binding is based on index into array, thats why all entries have to have the same dynamic fields
b.Mode = BindingMode.TwoWay;
c.Binding = b;
dtgResults.Columns.Add(c);
}
}
public IList<MyDimension> CreateData()
{
List<MyDimension> Dimensions = new List<MyDimension>();
string[] names = new string[] { "PART11", "PART20" }; // They must all have the same obcItemsName/obcItemsMeasured entries, and in the same order
Dimensions.Add(CreateItem("LOC1-X", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-Y", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-D", names, 10.0, 10.1));
Dimensions.Add(CreateItem("LOC1-RN", names, 0, 0));
Dimensions.Add(CreateItem("LOC2-X", names, 0, 0));
Dimensions.Add(CreateItem("LOC2-Y", names, 0, 0));
Dimensions.Add(CreateItem("LOC1-DF", names, 10.2, 10.3));
Dimensions.Add(CreateItem("LOC2-TP", names, 0, 0));
Dimensions.Add(CreateItem("DIST1-M", names, 14.14214, 14.14215));
Dimensions.Add(CreateItem("DIST2-M", names, 10.4, 10.5));
// etc...
return Dimensions;
}
public MyDimension CreateItem(string name, string[] names, params double[] values)
{
var d = new MyDimension();
d.NameAxisDimension = name;
for (int i = 0; i < names.Length; i++)
{
d.obcItemsName.Add(names[i]);
d.obcItemsMeasured.Add(values[i]);
}
return d;
}
}
public class MyDimension
{
public MyDimension()
{
obcItemsName = new ObservableCollection<string>();
obcItemsMeasured = new ObservableCollection<double>();
}
public string NameAxisDimension { get; set; }
public double Nominal { get; set; }
public double UpperTolerance { get; set; }
public double LowerTolerance { get; set; }
public ObservableCollection<string> obcItemsName;
public ObservableCollection<double> obcItemsMeasured { get; set; } // Has to be a property since it is used in the binding
}
}
截图: