asp.Net GridView ligamento objeto personalizado com lista aninhada
-
08-07-2019 - |
Pergunta
Eu tenho uma lista de objeto personalizado, que consistem em uma lista personalizada.
class person{
string name;
int age;
List<friend> allMyFriends;
}
class friend{
string name;
string address;
}
I'trying para vincular uma lista desses objetos para um GridView ea grade deve criar para cada amigo uma coluna e escreva o nome nele. Se algumas pessoas têm o mesmo frined a grade não deve criar uma coluna separada, mas usar o já existente. Você sabe o que eu quero dizer. (As classes são apenas algumas classes de amostra para simplificar meu caso)
Existe uma maneira de personalizar dinamicamente a ligação?
posso alterar as definições de classe e assim por diante, se eles precisam para herdar de algumas interfaces ou assim por diante.
Eu pesquisei muito, mas nenhum exemplo realmente parecia cobrir este caso.
Poderia o uso de um objectSourceControl resolver o meu problema de alguma forma?
Update:
Para dar mais algumas informações: No final, eu tenho uma lista de pessoas, enquanto cada pessoa na lista tem uma lista de amigos.
List<person> allPerson = new List<person>();
// fill the list
Grid.DataSource = allPerson;
Grid.DataBind()
A tabela deve ter colunas para cada amigo e as linhas são a pessoa. Quando uma pessoa tem um amigo uma cruz (ou qualquer outro) precisa ser colocado na grade.
friend1 friend2
x peter
x x adam
No momento a interceptar o evento RowDataBound e desde que a ligação só cria as linhas com os nomes e não as colunas, porque a única propriedade na minha pessoa objeto é o nome. Existe uma maneira de forçar a ligação a olhar através da lista de propriedade na pessoa objetos e criar uma coluna para cada um deles.
Solução
Eu era capaz de resolver isso usando um DataTable como sua fonte de dados para o Grid. Eu não gosto da idéia de se mover de um objeto limpa agradável a um DataTable, mas fornece suporte para a ligação dinâmica que você precisa. Eu modifiquei o seu amigo objeto de ter alguns construtores. Isso me permitiu limpeza a declaração de código estático, mas pode não ser necessário em seu implmentation.
A idéia básica é que você vai passar por todos os amigos, adicione seu nome como um DataColumn em um DataTable, em seguida, preencha os dados de todos os objetos pessoa e seus respectivos amigos. Isto poderia provavelmente ser escrito para o trabalho em uma única iteração do objeto allPerson mas preferi duas iterações para tornar o código mais fácil de ler.
A solução é escrito para c # 3.5, mas poderia ser convertida para versões mais antigas, alterando a declaração de dados estáticos. Espero que isso ajude.
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;
}
}
Edit: I esqueceu de acrescentar como isso é renderizado.
-------------------------------------------------
| 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 | | | | |
-------------------------------------------------
Outras dicas
Parece que você está tentando exibir uma matriz / tabela de referência cruzada no GridView. Você pode achar que é mais fácil para agarrar sua recuperar seus dados em um formato mais compatível para isso. Você poderia considerar a escrever uma consulta de referência cruzada, se você estiver usando o servidor SQL.
Se você precisa trabalhar com os objetos na sua forma actual, Criando uma lista mesclada de amigos antes de iniciar também poderia ajudar, fornecendo a lista de colunas. Você poderia, então, ligar a cada coluna para uma chamada de função que poderia tentar encontrar a pessoa coluna na lista de linhas amigo.
Não bonito, mas poderia trabalhar ...
Tenha um olhar para a minha resposta a uma similar 'aninhados ligação' questão aqui .
Você também pode apenas usar o manipulador de eventos RowDataBound fazer ligações complexas.
use o seguinte:
DataBinder.Eval (Container.DataItem, "PPP.PPP")