asp.Net GridView связывает пользовательский объект с вложенным списком
-
08-07-2019 - |
Вопрос
У меня есть список настраиваемых объектов, который состоит из настраиваемого списка.
class person{
string name;
int age;
List<friend> allMyFriends;
}
class friend{
string name;
string address;
}
Я пытаюсь привязать список этих объектов к GridView, и Grid должен создать для каждого друга столбец и записать в него имя.Если у некоторых людей одинаковые настройки, сетка не должна создавать отдельный столбец, а использовать существующий.Если вы понимаете, о чем я.(Классы — это всего лишь примеры классов, чтобы упростить мой случай)
Есть ли способ динамически настроить привязку?
Я могу изменить определения классов и так далее, если им нужно наследовать какие-то интерфейсы и так далее.
Я много гуглил, но ни один пример, похоже, не отражал этот случай.
Может ли использование objectSourceControl каким-то образом решить мою проблему?
Обновлять:
Чтобы дать дополнительную информацию:В итоге у меня есть список людей, а у каждого человека в списке есть список друзей.
List<person> allPerson = new List<person>();
// fill the list
Grid.DataSource = allPerson;
Grid.DataBind()
В таблице должны быть столбцы для каждого друга, а строки — для человека.Если у человека есть друг, в сетке нужно поставить крестик (или что-то еще).
friend1 friend2
x peter
x x adam
На данный момент происходит перехват события RowDataBound, и поскольку привязка создает только строки с именами, а не столбцы, потому что единственным свойством моего объекта person является имя.Есть ли способ заставить привязку просматривать свойство List в объектах person и создавать столбец для каждого из них.
Решение
Мне удалось решить эту проблему, используя DataTable в качестве источника данных для Grid.Мне не нравится идея перехода от красивого чистого объекта к DataTable, но она обеспечивает поддержку необходимой вам динамической привязки.Я изменил объект вашего друга, добавив в него несколько конструкторов.Это позволило мне очистить объявление статического кода, но в вашей реализации это может не понадобиться.
Основная идея заключается в том, что вы просматриваете всех возможных друзей, добавляете их имена в качестве столбца данных в DataTable, а затем заполняете данные для всех объектов-людей и их друзей.Вероятно, это можно было бы написать для работы за одну итерацию объекта allPerson, но я предпочел две итерации, чтобы код было легче читать.
Решение написано для C# 3.5, но его можно преобразовать для более старых версий, изменив объявление статических данных.Надеюсь, это поможет.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// setup your person object with static data for testing
List<person> allPerson = new List<person>()
{
new person()
{
name = "Dan",
age = 21,
allMyFriends = new List<friend>() { new friend("James"), new friend("John"), new friend("Matt") }
},
new person()
{
name = "James",
age = 21,
allMyFriends = new List<friend>() { new friend("Dan"), new friend("Matt"), new friend("Tom") }
},
new person()
{
name = "John",
age = 21,
allMyFriends = new List<friend>() { new friend("Dan") }
},
new person()
{
name = "Matt",
age = 21,
allMyFriends = new List<friend>() { new friend("Dan"), new friend("James") }
},
new person()
{
name = "Tom",
age = 21,
allMyFriends = new List<friend>() { new friend("James") }
}
};
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
foreach (person p in allPerson)
{
// step through each person and look at their friends
foreach (friend f in p.allMyFriends)
{
// look to see if this friend has a column already
if (!dt.Columns.Contains(f.name))
{
dt.Columns.Add(f.name);
}
}
}
foreach (person p in allPerson)
{
// create the datarow that represents the person
System.Data.DataRow dr = dt.NewRow();
dr["Name"] = p.name;
dr["Age"] = p.age;
// find the friends and mark them
foreach (friend f in p.allMyFriends)
{
dr[f.name] = "X";
}
dt.Rows.Add(dr);
}
// fill the list
this.Grid.DataSource = dt;
this.Grid.DataBind();
}
}
public class person
{
public string name;
public int age;
public List<friend> allMyFriends = new List<friend>();
}
public class friend
{
public string name;
public string address;
public friend()
{
}
public friend(string name)
{
this.name = name;
}
public friend(string name, string address)
{
this.name = name;
this.address = address;
}
}
Редактировать:Я забыл добавить, как это отображается.
-------------------------------------------------
| Name | Age | James | John | Matt | Dan | Tom |
-------------------------------------------------
| Dan | 21 | X | X | X | | |
| James | 21 | | | X | X | X |
| John | 21 | | | | X | |
| Matt | 21 | X | | | X | |
| Tom | 21 | X | | | | |
-------------------------------------------------
Другие советы
Похоже, вы пытаетесь отобразить матрицу / кросс-таблицу в GridView. Возможно, вам будет проще получить ваши данные в формате, более совместимом с этим. Вы можете написать перекрестный запрос, если используете сервер SQL.
Если вам необходимо работать с объектами в их текущей форме, создание объединенного списка друзей перед началом также может помочь, предоставив список столбцов. Затем вы можете привязать к каждому столбцу вызов функции, который может попытаться найти человека столбца в списке друзей строк.
Не красиво, но может работать ...
Посмотрите на мой ответ на похожий вопрос «вложенного связывания» здесь .
Вы также можете просто использовать обработчик событий RowDataBound для создания сложных привязок.
используйте следующее :
DataBinder.Eval(Container.DataItem, «PPP.PPP»)