简体   繁体   English

如何在 blazor 中创建通用 treeview 组件?

[英]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
    }
  1. Index.razor索引.razor
<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM