#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.