Привязать linkedlist к datagridview

#c# #data-binding #datagridview #linked-list

#c# #привязка к данным #datagridview #связанный список

Вопрос:

Я пытаюсь привязать linkedlist к datagridview. Приведенный ниже метод работает для свойств в классе, за исключением массива. Если я объявляю массив как новый экземпляр, linkedlist создается правильно, но массив не привязан к datagridview. Если массив создается как свойство (я думаю, что код правильный), это приводит An unhandled exception of type 'System.StackOverflowException' occurred к созданию linkedlist.

Спасибо за любую помощь.

     public class PayoffNode
                {
                    public int DealNo { get; set; }
                    public string Category { get; set; }
                    public string Strategy { get; set; }
                    public string GreekType { get; set; }
                    // declare array as instance or as a property?
                    //public double[] Data = new double[22];  
                    public double[] Data
                    {
                        get { return Data; }
                        set { Data = value; }
                    }
                }

    LinkedList<Globals.PayoffNode> PayLL = new LinkedList<Globals.PayoffNode>();
                Random Rnd = new Random();
                for (int K = 1; K <= 10; K  )
                {
                    var T = new Globals.PayoffNode();
                    T.Category = "Account=="   K;
                    T.GreekType = "Greek=="   K;
                    T.DealNo = K;
                    T.Strategy = "Strategy=="   K;
                    for (int DP = 1; DP <= 21; DP  )
                    {
                        T.Data[DP] = Rnd.Next(10, 99);
                    }
                    PayLL.AddLast(T);
                }

                List<Globals.PayoffNode> qP = (from P in PayLL
                                               where P.Category == "Account==4" amp;amp; P.DealNo == 4 amp;amp; P.GreekType == "Greek==4" amp;amp; P.Strategy == "Strategy==4"
                                               select P).ToList();

     PayoffTable.DataSource = qP;
  

Обновить:
Спасибо за комментарии, кажется, это работает.

 public class PayoffNode
            {
                public int DealNo { get; set; }
                public string Category { get; set; }
                public string Strategy { get; set; }
                public string GreekType { get; set; }
                public double Data1 { get; set; }
                public double Data2 { get; set; }
                public double Data3 { get; set; }
                public double[] Data = new double[22];
            }

LinkedList<Globals.PayoffNode> PayLL = new LinkedList<Globals.PayoffNode>();
            Random Rnd = new Random();
            for (int K = 1; K <= 10; K  )
            {
                var T = new Globals.PayoffNode();
                T.Category = "Account=="   K;
                T.GreekType = "Greek=="   K;
                T.DealNo = K;
                T.Strategy = "Strategy=="   K;
                for (int DP = 1; DP <= 21; DP  )
                {
                    T.Data[DP] = Rnd.Next(10, 99);
                }
                PayLL.AddLast(T);
            }

List<Globals.PayoffNode> qP = (from P in PayLL
                                           where P.Category == "Account==4" amp;amp; P.DealNo == 4 amp;amp; P.GreekType == "Greek==4" amp;amp; P.Strategy == "Strategy==4"
                                           select new Globals.PayoffNode()
                                           {
                                               Category=P.Category,
                                               DealNo=P.DealNo,
                                               GreekType=P.GreekType,
                                               Strategy=P.Strategy,
                                               Data1=P.Data[1],
                                               Data2 = P.Data[2],
                                               Data3 = P.Data[3],
                                           }).ToList();

PayoffTable.DataSource = qP;
  

Комментарии:

1. return Data; это вызывает бесконечную рекурсию.

2. Что, по вашим ожиданиям, произойдет, если вы привяжете array к столбцу datagridview?

3. Я надеюсь увидеть, что каждая запись в datagridview будет выглядеть следующим образом: Category-GreekType-DealNo-Strategy-Data[1]-Data[2]... Итак, все переменные, а затем массив

4. Хотелось бы, чтобы это было так просто, но, к сожалению, каждое общедоступное свойство привязано только к одному столбцу, поэтому вам понадобится отдельное свойство Data1, Data2 и т.д. Для каждого столбца.

5. Да, вы правы, я ожидал слишком многого от запроса. Пожалуйста, взгляните на мое обновление и посмотрите, можете ли вы сделать его немного более эффективным?

Ответ №1:

Один из способов избежать создания 21 свойства данных — преобразовать список в DataTable:

 class PayoffNode
{
    public int DealNo;
    public string Category;
    public double[] Data; // = new double[21];
}
  

и затем

 Random Rnd = new Random();

List<PayoffNode> PayLL = Enumerable.Range(1, 10).Select(i => new PayoffNode {
    DealNo = i,
    Category = "Account=="   i,
    Data = Enumerable.Range(1, 21).Select(d => (double)Rnd.Next(10, 99)).ToArray()
}).ToList();

// List<PayoffNode> to DataTable
var dt = new DataTable();
dt.Columns.Add("DealNo", typeof(int));
dt.Columns.Add("Category"); // typeof(string) by default
for (int i = 1; i <= 21; i  )
    dt.Columns.Add("Data"   i, typeof(double));

foreach (var P in PayLL)
{
    var dr = dt.Rows.Add(P.DealNo, P.Category);
    for (int i = 0; i < 21; i  )
        dr[i 2] = P.Data[i]; //  2 is the number of fields before the Data fields
}

PayoffTable.DataSource = dt;
dt.DefaultView.RowFilter = " Category = 'Account==4' ";
  

Преимущество в том, что вы устанавливаете DataSource только один раз и просто меняете RowFilter , чтобы отфильтровать его. Кроме того, любые изменения, внесенные в DataGridView , изменяют DataTable и наоборот.

Обратите внимание, что массивы в C # и большинстве других языков начинаются с 0, а не с 1 ( .Data[0] для доступа к первому элементу в массиве), поэтому цикл for для доступа к массиву данных в моем примере составляет от 0 до 20.

Комментарии:

1. Спасибо, это выглядит намного эффективнее. Я просто предпочитаю использовать массивы базы 1.

Ответ №2:

 public double[] Data
{
    get { return Data; }
    set { Data = value; }
}
  

Это проблема, объект в set и методе get должен ссылаться на другой объект, иначе всякий раз, когда значение объекта устанавливается или пытается быть извлечено, он будет просто продолжать вызывать эти методы бесконечно. должно быть…

 private double[] _data;
public double[] Data
{
    get { return _data; }
    set { _data = value; }
}
  

или…

 public double[] Data { get; set; }
  

Комментарии:

1. Я согласен, но ваш ответ не работает. Я получаю сообщение об ошибке в строке T.Data[DP] = Rnd.Next(10, 99); со словами Object reference not set to an instance of an object.