Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从对象填充树视图_C#_.net_Winforms_Linq To Sql_Treeview - Fatal编程技术网

C# 从对象填充树视图

C# 从对象填充树视图,c#,.net,winforms,linq-to-sql,treeview,C#,.net,Winforms,Linq To Sql,Treeview,我的WinForm应用程序中的treeview有问题。我创建了一个保存数据的TreeViewItem类。只有5个字段:CaseNoteID、ContactDate、ParentNoteID、InsertUser、ContactDetails。 public class TreeItem { public Guid CaseNoteID; public Guid? ParentNoteID; public string ContactDate; public str

我的WinForm应用程序中的
treeview
有问题。我创建了一个保存数据的TreeViewItem类。只有5个字段:CaseNoteID、ContactDate、ParentNoteID、InsertUser、ContactDetails。

public class TreeItem
{
    public Guid CaseNoteID;
    public Guid? ParentNoteID;
    public string ContactDate;
    public string InsertUser;
    public string ContactDetails;

    public TreeItem(Guid caseNoteID, Guid? parentNoteID, string contactDate, string contactDetails, string insertUser)
    {
        CaseNoteID = caseNoteID;
        ParentNoteID = parentNoteID;
        ContactDate = contactDate;
        ContactDetails = contactDetails;
        InsertUser = insertUser;
    }
}
计划是通过在父项下显示一个由ParentNoteID字段确定的注释来显示注释之间的关系。真是太简单了。不幸的是,到目前为止,我所有的尝试都在两个位置都放置了一个“child”注释,其中一个带有ParentNoteID。第一级及其相应父级下的

当我逐步完成我的代码时,我的数据会准确地返回

 List<TreeItem> items = BLLMatrix.GetTreeViewData(HUD.PersonId);
        PopulateTree(tvwCaseNotes,items);
我只是好像没办法控制住它。我是否需要拆分我的数据调用,首先返回所有带有
ParentNoteID=null
的条目,然后获取其余的条目并以某种方式将它们合并起来


@霍根:我为问题中的剧烈变化道歉。从你的回答中可以明显看出,我一开始并没有从一个好的角度来看待这个问题。其次,原始方法仍然不起作用。

递归的基本思想是将堆栈用作每次调用变量的临时存储。但是,在递归调用中引用的是全局变量。当您更改它时(通过filter函数),它将使递归中所有先前的调用无效。您需要删除递归或在堆栈上推送控制变量(行)的新副本(而不是像现在这样的引用)

根据评论进行编辑

我讨厌在没有测试的情况下把代码放在那里,但我相信这样做应该可以解决我描述的问题

以下是问题所在:

// using the Find method uses a Predicate generic delegate.
if (nodeList.Find(FindNode) == null)
{
  var tmpCNoteID = dr["CaseNoteID"].ToString();
  var filter = "ParentNote='" + tmpCNoteID + "'";

  DataRow[] childRows = cNoteDT.Select(filter);

  if (childRows.Length > 0)
  {
    // Recursively call this function for all childRows
    TreeNode[] childNodes = RecurseRows(childRows);

    // Add all childnodes to this node
    node.Nodes.AddRange(childNodes);
  }

  // Mark this noteID as dirty (already added)
  nodeList.Add(node);
}
类似这样的东西应该可以解决我看到的问题(注意:这不是优雅或好的代码,它只是解决了我上面描述的问题,我永远不会把我的名字写在这段代码中)。而且,如果不能测试代码,我甚至不能确定这就是问题所在

// using the Find method uses a Predicate generic delegate.
if (nodeList.Find(FindNode) == null)
{
  var tmpCNoteID = dr["CaseNoteID"].ToString();
  var filter = "ParentNote='" + tmpCNoteID + "'";

  DataTable DTCopy = cNoteDT.Copy()

  DataRow[] childRows = DTCopy.Select(filter);

  if (childRows.Length > 0)
  {
    // Recursively call this function for all childRows
    TreeNode[] childNodes = RecurseRows(childRows);

    // Add all childnodes to this node
    node.Nodes.AddRange(childNodes);
  }

  // Mark this noteID as dirty (already added)
  nodeList.Add(node);
}

递归的基本思想是使用堆栈作为每次调用变量的临时存储。但是,在递归调用中引用的是全局变量。当您更改它时(通过filter函数),它将使递归中所有先前的调用无效。您需要删除递归或在堆栈上推送控制变量(行)的新副本(而不是像现在这样的引用)

根据评论进行编辑

我讨厌在没有测试的情况下把代码放在那里,但我相信这样做应该可以解决我描述的问题

以下是问题所在:

// using the Find method uses a Predicate generic delegate.
if (nodeList.Find(FindNode) == null)
{
  var tmpCNoteID = dr["CaseNoteID"].ToString();
  var filter = "ParentNote='" + tmpCNoteID + "'";

  DataRow[] childRows = cNoteDT.Select(filter);

  if (childRows.Length > 0)
  {
    // Recursively call this function for all childRows
    TreeNode[] childNodes = RecurseRows(childRows);

    // Add all childnodes to this node
    node.Nodes.AddRange(childNodes);
  }

  // Mark this noteID as dirty (already added)
  nodeList.Add(node);
}
类似这样的东西应该可以解决我看到的问题(注意:这不是优雅或好的代码,它只是解决了我上面描述的问题,我永远不会把我的名字写在这段代码中)。而且,如果不能测试代码,我甚至不能确定这就是问题所在

// using the Find method uses a Predicate generic delegate.
if (nodeList.Find(FindNode) == null)
{
  var tmpCNoteID = dr["CaseNoteID"].ToString();
  var filter = "ParentNote='" + tmpCNoteID + "'";

  DataTable DTCopy = cNoteDT.Copy()

  DataRow[] childRows = DTCopy.Select(filter);

  if (childRows.Length > 0)
  {
    // Recursively call this function for all childRows
    TreeNode[] childNodes = RecurseRows(childRows);

    // Add all childnodes to this node
    node.Nodes.AddRange(childNodes);
  }

  // Mark this noteID as dirty (already added)
  nodeList.Add(node);
}

也许我完全误解了你,但是你有一个扁平的层次结构,每个元素都知道它的父元素。现在必须创建每个元素,然后建立层次结构。下面是此类实现的第一个快速示例(缺少循环检查、错误处理等):

公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
PopulateTreeView(treeView,SampleData());
}
私有IEnumerable SampleData()
{
返回新项目{CaseID=“1”};
返回新项目{CaseID=“2”};
返回新项目{CaseID=“3”};
返回新项目{CaseID=“4”,ParentID=“5”};
产生返回新项目{CaseID=“5”,ParentID=“3”};
返回新项目{CaseID=“6”};
产生返回新项目{CaseID=“7”,ParentID=“1”};
产生返回新项目{CaseID=“8”,ParentID=“1”};
}
私有void PopulateTreeView(树视图树,IEnumerable项)
{
Dictionary allNodes=new Dictionary();
foreach(项目中的var项目)
{
变量节点=CreateTreeNode(项目);
添加(item.CaseID,Tuple.New(item,node));
}
foreach(所有节点中的var kvp)
{
if(kvp.Value.First.ParentID!=null)
{
allNodes[kvp.Value.First.ParentID].Second.Nodes.Add(kvp.Value.Second);
}
其他的
{
tree.Nodes.Add(kvp.Value.Second);
}
}
}
私有树节点CreateTreeNode(项目)
{
var node=new TreeNode();
node.Text=item.CaseID;
返回节点;
}
}
公共类项目
{
公共字符串CaseID{get;set;}
公共字符串ParentID{get;set;}
}
公共类元组
{
公共元组(T优先)
{
第一=第一;
}
公共T第一个{get;set;}
}
公共类Tuple:Tuple
{
公共元组(T第一,T2第二)
:基础(第一)
{
秒=秒;
}
公共T2秒{get;set;}
}
公共静态类元组
{
//允许Tuple.New(1,“2”)而不是New Tuple(1,“2”)
公共静态元组新(T1)
{
返回新元组(t1);
}
新的公共静态元组(T1、T2)
{
返回新的元组(t1,t2);
}
}
什么是元组? 只需回答评论中的问题:

  • 看一看
  • 看看这个
它是一个简单的容器对象,包含两个其他对象。就这样

我使用它,因为在我的字典中有一个unqiue标识符(
string CaseID
),它引用两个对象(
TreeNode
Item
)。另一种方法是制作两个字典,分别为
Dictionary
Dictionary
,但由于存在1:1的关系,我采用了元组方法

也许可以将其重命名为
ItemTreeNodeContainer
,它会让您更清楚它在conc中的含义
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        PopulateTreeView(treeView1, SampleData());
    }

    private IEnumerable<Item> SampleData()
    {
        yield return new Item { CaseID = "1" };
        yield return new Item { CaseID = "2" };
        yield return new Item { CaseID = "3" };
        yield return new Item { CaseID = "4", ParentID = "5" };
        yield return new Item { CaseID = "5", ParentID = "3" };
        yield return new Item { CaseID = "6" };
        yield return new Item { CaseID = "7", ParentID = "1" };
        yield return new Item { CaseID = "8", ParentID = "1" };
    }

    private void PopulateTreeView(TreeView tree, IEnumerable<Item> items)
    {
        Dictionary<string, Tuple<Item, TreeNode>> allNodes = new Dictionary<string, Tuple<Item, TreeNode>>();

        foreach (var item in items)
        {
            var node = CreateTreeNode(item);
            allNodes.Add(item.CaseID, Tuple.Create(item, node));
        }

        foreach (var kvp in allNodes)
        {
            if (kvp.Value.Item1.ParentID != null)
            {
                allNodes[kvp.Value.Item1.ParentID].Item2.Nodes.Add(kvp.Value.Item2);
            }
            else
            {
                tree.Nodes.Add(kvp.Value.Item2);
            }
        }
    }

    private TreeNode CreateTreeNode(Item item)
    {
        var node = new TreeNode();
        node.Text = item.CaseID;

        return node;
    }

}

public class Item
{
    public string CaseID { get; set; }
    public string ParentID { get; set; }
}