65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC 中的树视图绑定

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (2投票s)

2015年6月30日

CPOL

2分钟阅读

viewsIcon

14728

树视图绑定的算法。

引言

很多时候,我们需要以treeview(树形视图)的形式显示数据,例如显示文件夹结构。这个解决方案的最佳特点是不必担心treeview的层级,因为我在很多关于treeview的文章中发现,它们都对层级有限制,或者层级是静态的。我们可以通过多种方式绑定treeview,例如通过 XML 或通过treeview对象,但使用 XML 的问题在于我们需要额外的逻辑来创建 XML。因此,我提供了一个非常简单的解决方案来绑定treeview,为此我们需要将数据存储在列表中。我将这篇文章详细阐述,以便它可以应用于任何类型的语言,这就是为什么我更专注于算法而不是源代码的原因。

算法

这个算法分为两个部分,即

  1. 为每个节点分配唯一值,以及
  2. 基于唯一值生成treeview

为每个节点分配唯一值

算法

  1. 从列表中获取下一个项目并按“/”分割
  2. 从分割后的项目中获取下一个节点
  3. 如果节点包含扩展名,则直接返回到步骤 a。
  4. 如果节点索引为零,则在节点后附加一些文本,例如“<N1>”。
  5. 如果节点索引大于零,则以以下方式在节点后附加文本
    1. 节点=节点的前一个字符(索引-1)+节点+节点后一个字符(索引+1)
  6. 返回到步骤 b。

源代码

Data <string>=
{
    "A/F1.txt"
    "A/B/F2.txt"
    "A/B/F3.txt"
    "A/B/C/F4.txt"
    "A/B/C/F5.txt"
    "A/D/C/F6.txt"
    "A/D/C/F7.txt"
}
List<string> Data = new List<string>();
List<string> ResultData = new List<string>();
for (int i = 0; i < Data.Count; ++i)
{
    string Result = "";
    Data[i] = Data[i].Replace('\\', '/');
    for (int j = 0; j < Data[i].Split('/').Length; ++j)
    {
        string BindText = Data[i].Split('/')[j];
        if (j == 0)
        {
            BindText = BindText + "<12>";
            Result = BindText;
        }
        else if (BindText.Contains("."))
        {
            Result = Result + "/" + BindText;
        }
        else
        {
            BindText = BindText + "<" + Data[i].Split('/')[j - 1].Substring(0, 1) + 
            "XZE" + BindText.Substring(0, 1) + ">";
            Result = Result + "/" + BindText;
        }
    }
    ResultData.Add(Result);
}

示例

输入值

List= {
"A/F1.txt"
"A/B/F2.txt"
"A/B/F3.txt"
"A/B/C/F4.txt"
"A/B/C/F5.txt"
"A/D/C/F6.txt"
"A/D/C/F7.txt"
         }

输出值

List= {
"A<N1>/F1.txt"
"A<N1>/B<ABC>/F2.txt"
"A<N1>/B<ABC>/F3.txt"
"A<N1>/B<ABC>/C<BC>/F4.txt"
"A<N1>/B<ABC>/C<BC>/F5.txt"
"A<N1>/D<ADC>/C<DC>/F6.txt"
"A<N1>/D<ADC>/C<DC>/F7.txt"
           }

2. 基于先前算法分配的唯一 ID 生成 Treeview 对象

算法

  1. 声明 CurrentNodeRootNode
  2. 从列表中获取下一个项目并按“/”分割
  3. 从分割后的项目中获取下一个节点
  4. 如果节点是第一个项目且索引为零,则
    1. CurrentNode=CreateNode();
    2. RootNode=CurrentNode;
  5. 否则,如果节点索引为零,则
    1. CurrentNode= RootNode;
  6. 否则,如果节点是文件名,则
    1. MyNode= CreateNode();
    2. MyNode 添加到 CurrentNode
  7. Else
    1. Text=GetNodeName(node);
    2. ID=GetNodeID(node);
    3. CurrentNode 中查找 ID
      1. 如果不匹配,则
        1. MyNode=CreateNode()
        2. MyNode 添加到 CurrentNode
      2. 否则(表示匹配),则
        1. CurrentNode=GetNodeBasedOnID(ID);
  8. 如果节点是列表的最后一个项目,则退出
  9. 如果节点是最后一个项目,则转到步骤 b,否则转到步骤 c。

源代码

Data<string>=
{
    "A<N1>/F1.txt",
    "A<N1>/B<ABC>/F2.txt",
    "A<N1>/B<ABC>/F3.txt",
    "A<N1>/B<ABC>/C<BC>/F4.txt",
    "A<N1>/B<ABC>/C<BC>/F5.txt",
    "A<N1>/D<ADC>/C<DC>/F6.txt",
    "A<N1>/D<ADC>/C<DC>/F7.txt",
}
DocIDs<string>=
{
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7"
}
List<string> Data, List<string> DocIDs;
List<TreeItem> Root = new List<TreeItem>();
TreeItem RootNode = new TreeItem();
for (int i = 0; i < Data.Count; ++i)
{
    string Prev = "";
    string Next = "";
    TreeItem PreNode = new TreeItem();
    TreeItem CurrentNode = new TreeItem();
    CurrentNode = RootNode;
    for (int j = 0; j < Data[i].Split('/').Length; ++j)
    {
        string BindText = Data[i].Split('/')[j];
        string id = "";
        string text = "";
        if (i == 0 && j == 0)
        {
            text = BindText.Substring(0, BindText.IndexOf('<'));
            id = ((BindText.Replace(text, "")).Replace("<", 
            "")).Replace(">", "");
            CurrentNode = new TreeItem() { ID = id, Text = text };
            RootNode = CurrentNode;
        }
        else if (j == 0)
        {
            CurrentNode = RootNode;
        }
        else if (BindText.Contains("."))
        {
            text = BindText;
            CurrentNode.Items = new List<TreeItem>();
            CurrentNode.Items.Add(new TreeItem() { UniqueID = id, Text = text, ID = DocIDs[i] });
        }
        else
        {
            text = BindText.Substring(0, BindText.IndexOf('<'));
            //id = ((BindText.Replace(text, "")).Replace("<","")).Replace(">", "");

            BindText = BindText.Remove(0, BindText.IndexOf('<'));
            id = (BindText.Replace("<", "")).Replace(">", "");
            if (CurrentNode.Items == null)
            {
                CurrentNode.Items = new List<TreeItem>();
            }
            if (CurrentNode.Items.Count(m => m.UniqueID == id) == 0)
            {
                PreNode = CurrentNode;
                CurrentNode = new TreeItem() { UniqueID = id, Text = text, ID = DocIDs[i] };
                //PreNode.Items = new List<TreeItem>();
                PreNode.Items.Add(CurrentNode);
            }
            else
            {
                CurrentNode = CurrentNode.Items.Single(m => m.UniqueID == id);
            }
        }
    }
}
Root.Add(RootNode);
return Root;

实现 Treeview 的步骤

请按照以下步骤操作

创建 TreeView 类

public class TreeItem
{
    public string Text { get; set; }
    public string ID { get; set; }
    public string URL { get; set; }
    public string UniqueID { get; set; }
    public string DetailText { get; set; }
    public List<TreeItem> Items { get; set; }        
}

创建 TreeBinder 类

public class TreeBinder
{
    private List<string> AssignUniqueValue(List<string> Data)
    {
        List<string> ResultData = new List<string>();
        for (int i = 0; i < Data.Count; ++i)
        {
            string Result = "";
            Data[i] = Data[i].Replace('\\', '/');
            for (int j = 0; j < Data[i].Split('/').Length; ++j)
            {
                string BindText = Data[i].Split('/')[j];
                if (j == 0)
                {
                    BindText = BindText + "<12>";
                    Result = BindText;
                }
                else if (BindText.Contains("."))
                {
                    Result = Result + "/" + BindText;
                }
                else
                {
                    BindText = BindText + "<" + Data[i].Split('/')[j - 1].Substring(0, 1) + 
                    "XZE" + BindText.Substring(0, 1) + ">";
                    Result = Result + "/" + BindText;
                }
            }
            ResultData.Add(Result);
        }
        return ResultData;
    }
    private List<TreeItem> GenerateTreeViewBasedOnUniueData(List<string> Data, List<string> DocIDs)
    {
        List<TreeItem> Root = new List<TreeItem>();
        TreeItem RootNode = new TreeItem();
        for (int i = 0; i < Data.Count; ++i)
        {
            string Prev = "";
            string Next = "";
            TreeItem PreNode = new TreeItem();
            TreeItem CurrentNode = new TreeItem();
            CurrentNode = RootNode;
            for (int j = 0; j < Data[i].Split('/').Length; ++j)
            {
                string BindText = Data[i].Split('/')[j];
                string id = "";
                string text = "";
                if (i == 0 && j == 0)
                {
                    text = BindText.Substring(0, BindText.IndexOf('<'));
                    id = ((BindText.Replace(text, "")).Replace
                    ("<", "")).Replace(">", "");
                    CurrentNode = new TreeItem() { ID = id, Text = text };
                    RootNode = CurrentNode;
                }
                else if (j == 0)
                {
                    CurrentNode = RootNode;
                }
                else if (BindText.Contains("."))
                {
                    text = BindText;
                    CurrentNode.Items = new List<TreeItem>();
                    CurrentNode.Items.Add(new TreeItem() { UniqueID = id, Text = text, ID = DocIDs[i] });
                }
                else
                {
                    text = BindText.Substring(0, BindText.IndexOf('<'));
                    //id = ((BindText.Replace(text, "")).Replace
                    //("<", "")).Replace(">", "");

            BindText = BindText.Remove(0, BindText.IndexOf('<'));
            id = (BindText.Replace("<", "")).Replace(">", "");
            if (CurrentNode.Items == null)
            {
                CurrentNode.Items = new List<TreeItem>();
            }
            if (CurrentNode.Items.Count(m => m.UniqueID == id) == 0)
            {
                PreNode = CurrentNode;
                CurrentNode = new TreeItem() { UniqueID = id, Text = text, ID = DocIDs[i] };
                //PreNode.Items = new List<TreeItem>();
                PreNode.Items.Add(CurrentNode);
            }
            else
            {
                CurrentNode = CurrentNode.Items.Single(m => m.UniqueID == id);
            }
        }
    }
}
Root.Add(RootNode);
return Root;

在视图中声明 TreeView 控件

<script type="text/javascript">
    function BindTreeView() {
        console.log("start");
        var url = '/NMA/LoadTree'//'@Url.Action("LoadTree", "NMA")';
        $.post(url,
        function (data) {
            console.log(data);
            $("#tree").igTree({
                dataSource: data, //JSON Array defined above
                bindings: {
                    textKey: "Text",
                    valueKey: "ID",
                    childDataProperty: "Items",
                    bindings: {
                        textKey: "Text",
                        valueKey: "ID"
                    }
                }
            });
        });
    }           
</script>
<button type="button" value="test" onclick="BindTreeView();">Click me</button>
<ul id="tree"></ul>

从控制器调用 tree binder 方法

public JsonResult LoadTree()
{
    string[] Data ={
                        "A/F1.txt",
                        "A/B/F2.txt",
                        "A/B/F3.txt",
                        "A/B/C/F4.txt",
                        "A/B/C/F5.txt",
                        "A/D/C/F6.txt",
                        "A/D/C/F7.txt"
                    };
    string[] DocIDs ={
                        "1",
                        "2",
                        "3",
                        "4",
                        "5",
                        "6",
                        "7"
                    };
    TreeBinder treObj = new TreeBinder();
    List<TreeItem> tree = treObj.GenerateTreeView(Data.ToList(), DocIDs.ToList());
    return Json(tree, JsonRequestBehavior.AllowGet);
}
© . All rights reserved.