[英]how to create a generic treeview component in blazor?
could you help me?你可以帮帮我吗? I want to make a generic tree view component in blazor webassembly but I am a bit lost in how to do it, I want to be able to pass any type of object list to the component, for the moment I have done something very simple, with an object called directory load the component but I would like to replace it with Titem to be able to send any type of list
我想在 blazor webassembly 中创建一个通用树视图组件,但我对如何做有点迷茫,我希望能够将任何类型的 object 列表传递给组件,目前我做了一些非常简单的事情,使用名为目录的 object 加载组件,但我想用 Titem 替换它以便能够发送任何类型的列表
index.razor索引.razor
@page "/index"
<h1>Treeview</h1>
<Treeview Directorios="directorios"></Treeview>
@code {
public Directorio[] directorios;
protected async override Task OnInitializedAsync()
{
var fall2014 = new Directorio("Fall 2014", new Directorio[] { }, new string[] { "image1.jpg", "image2.jpg", "image3.jpg" });
var summer2014 = new Directorio("Summer 2014", new Directorio[] { }, new string[] { "image10.jpg", "image20.jpg", "image30.jpg" });
var pictures = new Directorio("Pictures", new Directorio[] { fall2014, summer2014 }, new string[] { });
var music = new Directorio("Music", new Directorio[] { }, new string[] { "song1.mp3", "song2.mp3" });
directorios = new Directorio[] { pictures, music };
}
}
component.razor组件.razor
<ul>
@foreach (var dir in Directorios)
{
<li>
<span @onclick="@dir.toggle">@dir.getIcon()</span>
<span>@dir.nombre</span>
@if (dir.expanded)
{
<div>
<ul>
@foreach (var archivo in dir.archivos)
{
<li>@archivo</li>
}
</ul>
<Treeview Directorios="@dir.directorios"></Treeview>
</div>
}
</li>
}
</ul>
@code {
[Parameter] public Directorio[] Directorios { get; set; }
}
directory.cs目录.cs
public class Directorio
{
public bool expanded = false;
public string nombre;
public string[] archivos;
public Directorio[] directorios;
public Directorio(string nombre, Directorio[] directorios, string[] archivos)
{
this.nombre = nombre;
this.directorios = directorios;
this.archivos = archivos;
}
public void toggle()
{
expanded = !expanded;
}
public string getIcon()
{
if (expanded)
{
return "-";
}
return "+";
}
}
Try this one.试试这个。
In future perhaps I will make a combotree and share with you here.将来也许我会制作一个组合树并在这里与您分享。 if you are able to do same, do not hesitate to post it here.
如果你能做到这一点,不要犹豫,把它贴在这里。
1.Treeview.razor 1.Treeview.razor
@typeparam Tvalue
@inherits TreeBase<Tvalue>
<ul class="parentUl">
@if (AllItems != null)
{
@foreach (var Pitem in AllItems)
{
if (GetPropertyValue(Pitem, ParentId) == ""|| Convert.ToInt32(GetPropertyValue(Pitem, ParentId)) == 0)
{
if (Convert.ToBoolean(GetPropertyValue(Pitem, HasChildren)))
{
<li>
<span @onclick="@(()=>SpanToggle(Pitem))" class="@_caretcss[Convert.ToInt32(@GetPropertyValue(Pitem, Id))]">@GetPropertyValue(Pitem, Text)</span>
<ul class="@_nestedcss[Convert.ToInt32(@GetPropertyValue(Pitem, Id))]">
@foreach (var Citem in AllItems)
{
if (GetPropertyValue(Pitem, Id) == GetPropertyValue(Citem, ParentId))
{
if (Convert.ToBoolean(GetPropertyValue(Citem, HasChildren)))
{
<li>
<span @onclick="@(()=>SpanToggle(Citem))" class="@_caretcss[Convert.ToInt32(@GetPropertyValue(Citem, Id))]">@GetPropertyValue(Citem, Text)</span>
<ul class="@_nestedcss[Convert.ToInt32(@GetPropertyValue(Citem, Id))]">
@foreach (var C1item in AllItems)
{
if (GetPropertyValue(Citem, Id) == GetPropertyValue(C1item, ParentId))
{
if (Convert.ToBoolean(GetPropertyValue(C1item, HasChildren)))
{
<li>
<span @onclick="@(()=>SpanToggle(C1item))" class="@_caretcss[Convert.ToInt32(@GetPropertyValue(C1item, Id))]">@GetPropertyValue(C1item, Text)</span>
<ul class="@_nestedcss[Convert.ToInt32(@GetPropertyValue(C1item, Id))]">
@foreach (var C2item in AllItems)
{
if (GetPropertyValue(C1item, Id) == GetPropertyValue(C2item, ParentId))
{
if (Convert.ToBoolean(GetPropertyValue(C2item, HasChildren)))
{
<li>
<span @onclick="@(()=>SpanToggle(C2item))" class="@_caretcss[Convert.ToInt32(@GetPropertyValue(C2item, Id))]">@GetPropertyValue(C1item, Text)</span>
</li>
}
else
{
<li>@GetPropertyValue(C2item, Text)</li>
}
}
}
</ul>
</li>
}
else
{
<li>@GetPropertyValue(C1item, Text)</li>
}
}
}
</ul>
</li>
}
else
{
<li>@GetPropertyValue(Citem, Text)</li>
}
}
}
</ul>
</li>
}
else
{
<li>@GetPropertyValue(Pitem, Text)</li>
}
}
}
}
</ul>
2.style.css 2.style.css
<style type="text/css">
/*css reference W3schools. "with small modification."*/
/* css begin*/
.parentUl li ul {
border-left: dashed 2px black;
height: fit-content;
border-start-end-radius: 2px;
}
ul, .parentUl {
list-style-type: none;
}
.parentUl ul li {
position: relative;
}
.parentUl ul li:before {
content: "";
position: absolute;
top: 13px;
left: -40px;
width: 40px;
height: 1px;
border-bottom: dashed 2px black;
}
.parentUl {
margin: 0;
padding: 0;
}
.caret {
cursor: pointer;
-webkit-user-select: none; /* Safari 3.1+ */
-moz-user-select: none; /* Firefox 2+ */
-ms-user-select: none; /* IE 10+ */
user-select: none;
}
.caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
transition: all 0.45s;
}
.caret-down::before {
-ms-transform: rotate(60deg); /* IE 9 */
-webkit-transform: rotate(60deg); /* Safari */
transform: rotate(60deg);
transition: all 0.45s;
}
.nested {
display: none;
transition: all 0.45s;
}
.active {
display: block;
transition: all 0.45s;
}
/*css end*/
</style>
3.TreeviewBase.cs 3.TreeviewBase.cs
public partial class TreeBase<Tvalue>:ComponentBase
{
[Parameter]
public List<Tvalue> DataSource { get; set; }
[Parameter]
public string Id { get; set; }
[Parameter]
public string ParentId { get; set; }
[Parameter]
public string HasChildren { get; set; }
[Parameter]
public string Text { get; set; }
[Parameter]
public string Expanded { get; set; }
protected List<Tvalue> AllItems;
protected Dictionary<int, bool> _caretDown= new Dictionary<int, bool>();
protected Dictionary<int, string> _caretcss=new Dictionary<int,string>();
protected Dictionary<int, string> _nestedcss=new Dictionary<int,string>();
protected override Task OnInitializedAsync()
{
//asigning to its new instance to avoid exceptions.
AllItems = new List<Tvalue>();
AllItems = DataSource.ToArray().ToList();
if (AllItems != null)
{
foreach (var item in AllItems)
{
var _id = Convert.ToInt32(GetPropertyValue(item, Id));
//initializing fields with default value.
_caretDown.Add(_id, true);
_caretcss.Add(_id, "caret");
_nestedcss.Add(_id, "nested");
}
}
return base.OnInitializedAsync();
}
protected override Task OnParametersSetAsync()
{
//This will check if the first item in the
// list/collection has a "parentId" then remove the "parentId" from it.
//Because we use the first item as a reference in the razor file, so it must not have "parentId".
var Parem = AllItems.First();
switch (GetPropertyType(Parem, ParentId))
{
case "Int32":
if (Convert.ToInt32(GetPropertyValue(Parem, ParentId)) > 0)
{
SetPropertyValue<int>(Parem, ParentId, 0);
}
break;
case "String":
if (GetPropertyValue(Parem, ParentId) != "")
{
SetPropertyValue<string>(Parem, ParentId, "");
}
break;
default:
break;
}
return base.OnParametersSetAsync();
}
protected void SpanToggle(Tvalue item)
{
var _clckdItemid = Convert.ToInt32(GetPropertyValue(item, Id));
_caretcss[_clckdItemid] = _caretDown[_clckdItemid] ? "caret caret-down" : "caret";
_nestedcss[_clckdItemid] = _caretDown[_clckdItemid] ? "active" : "nested";
_caretDown[_clckdItemid] = !_caretDown[_clckdItemid];
}
#region reflection methodes to get your property type, propert value and also set property value
protected string GetPropertyValue(Tvalue item, string Property)
{
if (item != null)
{
return item.GetType().GetProperty(Property).GetValue(item, null).ToString();
}
return "";
}
protected void SetPropertyValue<T>(Tvalue item, string Property, T value)
{
if (item != null)
{
item.GetType().GetProperty(Property).SetValue(item, value);
}
}
protected string GetPropertyType(Tvalue item, string Property)
{
if (item != null)
{
return item.GetType().GetProperty(Property).PropertyType.Name;
}
return null;
}
#endregion
}
<Tree Tvalue="MailItem" DataSource="@MyFolder" Id="Id" Text="FolderName" ParentId="ParentId"
Expanded="Expanded" HasChildren="HasSubFolder"></Tree>
@code{
protected class MailItem
{
public int Id { get; set; }
public string ParentId { get; set; }
public bool HasSubFolder { get; set; }
public string FolderName { get; set; }
public bool Expanded { get; set; }
}
List<MailItem> MyFolder = new List<MailItem>();
protected override Task OnInitializedAsync()
{
MyFolder.Add(new MailItem { Id = 1, FolderName = "Inbox", HasSubFolder = true, Expanded = true, ParentId = "" });
MyFolder.Add(new MailItem { Id = 2, FolderName = "Category", ParentId = "1", HasSubFolder = true, Expanded = true });
MyFolder.Add(new MailItem { Id = 3, FolderName = "Primary", ParentId = "2", HasSubFolder = false, Expanded = true });
MyFolder.Add(new MailItem { Id = 4, FolderName = "Social", ParentId = "6", HasSubFolder = false, Expanded = true });
MyFolder.Add(new MailItem { Id = 5, FolderName = "Promotion", ParentId = "6", HasSubFolder = false, Expanded = true });
MyFolder.Add(new MailItem { Id = 6, FolderName = "Demo", ParentId = "2", HasSubFolder = true, Expanded = true });
return base.OnInitializedAsync();
}
}
Kindly click on this image to view the working example:请单击此图像以查看工作示例:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.