Como ligar asp.net controles usando uma auto juntar e itens tabelas “estrutura hierárquica”?
-
22-08-2019 - |
Pergunta
Eu tenho as seguintes tabelas:
1-Categorias:
-CategoryID
-CategoryName
-ParentID
2-Artigos:
-ItemId
-ItemName
-CategoryID
categorias podem estar em uma hierarquicamente ver, com muitas categorias crianças dentro uns dos outros.
E qualquer categoria a última criança pode ter itens, então apenas a última categoria filho vai mostrar os itens sob ele.
A exibição será como um treeview e ao clicar em um item que vai para uma nova página.
Escrevi-o assim:
<asp:Repeater runat="server" ID="rptCategories" OnItemDataBound="rptCategories_ItemDataBound" >
<ItemTemplate>
<div id="type_<%# Eval("Type") %>">
<p >
<a id="<%# Eval("CategoryID") %>" class="Categories">
<%# Eval("CategoryName") %></a>
</p>
<div id="ProjectsDiv_<%# Eval("CategoryID") %>" class="Projects">
<asp:Repeater ID="rptProjects" runat="server">
<ItemTemplate>
<a id="<%# Eval("ProjectID") %>" class="ProjectLink">
<%# GetProject(Eval("ProjectID"))%>
</a>
</ItemTemplate>
</asp:Repeater>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
mas isso representa uma estrutura de nível um,
A minha pergunta é como fazê-lo como uma árvore?
Solução
Este vai ser complicado com um repetidor, se você não sabe a profundidade da hierarquia vai. Por que não usar apenas um asp.net TreeView?
http://msdn.microsoft .com / en-us / library / system.web.ui.webcontrols.treeview.aspx
Você pode usar asp.net ajax e um updatepanel para alcançar o efeito desejado sem escrever qualquer JavaScript si mesmo.
Outras dicas
Para fazer isso você precisa de duas classes -. Um para um árvore-como controle, eo outro que alimenta os dados para o controle em uma hierarquia
-
Para o controle, você pode simplesmente usar algo como um TreeView , ou você pode escrever seu próprio herdando de HierarchalDataBoundControl .
-
Para a fonte de dados, uma vez que você tem um muito específico e formato personalizado de seus dados, você precisa escrever uma classe que implementa IHierarchalDataSource . Essa classe vai se tornar a fonte de dados de seu controle, e quando você chamar DataBind, vai alimentar o controle dos dados de uma forma hierárquica.
Aqui está um tutorial sobre como construir uma HierarchalDataBoundControl a partir do zero.
Outra opção é recursão uso justo e ser rápido e sujo sobre isso. Eu respondi uma pergunta relacionada a este aqui .
if (! IsPostBack) { Preencher (TreeView1.Nodes);
}
}
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
TreeNode node = TreeView1.SelectedNode;
string nodeId = node.Value;
string nodeName = node.Text;
}
private void Populate(TreeNodeCollection nodes)
{
TreeNode parentNode = null;
foreach (Category1 category in GetProductCategories())
{
parentNode = new TreeNode(category.Name, category.Id.ToString());
if (category.Subcategories != null)
{
SubNodes(category, parentNode);
}
parentNode.Collapse();
TreeView1.Nodes.Add(parentNode);
}
}
private void SubNodes(Category1 category, TreeNode childNode)
{
foreach (Category1 c1 in category.Subcategories)
{
TreeNode subchildnode = new TreeNode(c1.Name, c1.Id.ToString());
childNode.ChildNodes.Add(subchildnode);
if (c1.Subcategories != null)
{
SubNodes(c1, subchildnode);
}
}
}
protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
}
#region unwanted
// Show all checkboxes
//TreeView1.ShowCheckBoxes = TreeNodeTypes.All;
//protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
//{
// PopulateSubLevel(Int32.Parse(e.Node.Value), e.Node);
//}
//private void PopulateSubLevel(int parentid, TreeNode parentnode)
//{
// Populate1( parentid,parentnode.ChildNodes);
//}
//private void Populate1(int k1,TreeNodeCollection nodes)
//{
// foreach (var j in GetProductCategories())
// {
// if (j.ParentId == k1)
// {
// foreach (var k in j.Subcategories)
// {
// TreeNode tn = new TreeNode();
// tn.Text = k.Name;
// tn.Value = k.ParentId.ToString();
// nodes.Add(tn);
// //tn.PopulateOnDemand = ((int)(k.Subcategories.Count) > 0);
// }
// // break;
// }
// }
//}
#endregion
#region class
//public List<Category1> GetProductCategories()
//{
// return new List<Category1> {
// new Category1{Id=1,Name="Power Tools",ParentId=0,Sequence=1,Description="Power Tools",DisplayInHeader=true,
// Subcategories = new List<Category1>
// {new Category1{Id=100,Name="Drills",ParentId=1,Sequence=1,Description="Drills",DisplayInHeader=true},
// new Category1{Id=101,Name="Drill Accessories",ParentId=1,Sequence=1,Description="Drill Accessories",DisplayInHeader=true},
// new Category1{Id=102,Name="Saws",ParentId=0,Sequence=1,Description="Saws",DisplayInHeader=true}
// }},
// new Category1{Id=2,Name="Cordless Tools",ParentId=1,Sequence=1,Description="Cordless Tools",DisplayInHeader=true,
// Subcategories = new List<Category1>
// {new Category1{Id=200,Name="Batteries/Chargers",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true}
// }},new Category1{Id=3,Name="AirTools",ParentId=2,Sequence=1,Description="Air Tools",DisplayInHeader=true,
// Subcategories = new List<Category1>
// {new Category1{Id=300,Name="Portable Compressors",ParentId=0,Sequence=1,Description="Portable Compressors",DisplayInHeader=true},
// }}
// };
//}
#endregion
public List<Category1> GetProductCategories()
{
return new List<Category1> {
new Category1{Id=1,Name="Power Tools",ParentId=0,Sequence=1,Description="Power Tools",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=100,Name="Drills",ParentId=1,Sequence=1,Description="Drills",DisplayInHeader=true},
new Category1{Id=101,Name="Drill Accessories",ParentId=1,Sequence=1,Description="Drill Accessories",DisplayInHeader=true,
Subcategories= new List<Category1>{new Category1{Id=1001,Name="Drill Accessories",ParentId=101,Sequence=1,Description="Drill Accessories",DisplayInHeader=true,
Subcategories= new List<Category1>{new Category1{Id=1001,Name="Drill Accessories",ParentId=101,Sequence=1,Description="Drill Accessories",DisplayInHeader=true}}}}},
new Category1{Id=102,Name="Saws",ParentId=0,Sequence=1,Description="Saws",DisplayInHeader=true}
}},
new Category1{Id=2,Name="Cordless Tools",ParentId=1,Sequence=1,Description="Cordless Tools",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=200,Name="Batteries/Chargers",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=200,Name="Batteries",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=200,Name="Batteries",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=200,Name="Batteries",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=200,Name="Batteries",ParentId=2,Sequence=1,Description="Batteries/Chargers",DisplayInHeader=true}}}}}}}}}
}},new Category1{Id=3,Name="AirTools",ParentId=2,Sequence=1,Description="Air Tools",DisplayInHeader=true,
Subcategories = new List<Category1>
{new Category1{Id=300,Name="Portable Compressors",ParentId=0,Sequence=1,Description="Portable Compressors",DisplayInHeader=true},
}},
};
}
A Oracle teve uma declaração CONNECT BY que foi projetado para consultas hierárquicas. Pelo menos a partir de Sql Server 2005 Eu não acredito que havia um equivalente direto assim que você teve que fingir com procedimentos armazenados ...