Programmatically add columns to datagrid not compi

2019-09-02 18:59发布

This is the continuation to

OnEvent datagrid column add fail

I have seen this post:

How to add Data to a WPF datagrid programatically

the datagrid is simply this:

<DataGrid Name="dtgResults" Background="Transparent" AutoGenerateColumns="False"/>

in which everything seems to work fine but when I put it in my solution it doesn't compile:

enter image description here

Can anyone explain me why?

---EDIT---

I realize now that I have misunderstood what's in the link above. In short I have a datagrid binded to an observable collection. I have to add two more columns. How can that be done?

---EDIT2---- for 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" });

---EDIT 3--- for JH So in short I have that observable collection which binded to the datagrid make the following output:

enter image description here

then I add the columns with your method:

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);
    }

as for the binded array

enter image description here

enter image description here

and the bind str is "obcmMyDim.obcItemsMeasured[0]" ...1....n

but what I get is that the columns are there but they are empty

enter image description here

3条回答
家丑人穷心不美
2楼-- · 2019-09-02 19:39

You can bind to an item in an array but you'll have to make sure that all the arrays are the same (same fields, in the same order so that the index into them is consistent). Here is an example of it based on the other question you had.

Note that the field obcItemsMeasured had to be changed into a property since bindings require properties (not fields).

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>

Code:

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
    }
}

Screenshot:

enter image description here

查看更多
家丑人穷心不美
3楼-- · 2019-09-02 19:41

Have you tried something like;

dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.1"});
dtgResults.Columns.Add(new DataGridTextColumn { Header = "a.2"});

EDIT:

 for (int i = 1; i <= 10; i++)
 {
     dtgResults.Items.Add(new { a.1 = "Test" + i, a.2 = "Test" + i});
 }
查看更多
相关推荐>>
4楼-- · 2019-09-02 19:41

It does not compiling because you use ItemCollection. I think you did not create your own class like in answer from link and used System.Windows.Controls.ItemCollection, which can`t used in this case.

查看更多
登录 后发表回答