Dynamic Treenode Creation
I like the use of white space and indentation, makes the code easy to read.

I would start using var for your variable declarations.  It keeps the code cleaner, and easier for your eyes to scan.

Remove the // Do Nothing if statements.  It is redundant and adds extra lines of code that are unneeded.  This should work:

if (!subfeatSet.Contains(newNode.Text))
{
    treeviewFeatsFeats.Nodes.Add(newNode);
    foreach (DataRow subrow in ds.subfeats.Rows)
    {

    ...
}


I would also learn about linq, you can clean up most of your loops with linq.  I would also look into moving some of the inner loops out into their own function.  Moving to a function would remove some duplication you have in your code too.

private void ProcessNode(TreeNode parent, DataSet ds)
{
    var index = ds.subfeats.Columns.IndexOf("feat");
    foreach (var treeNode in (
            from row in ds.subfeats.Rows                
            let nodeName = Convert.ToString(row[index])
            where rows.Contains(nodeName)
            select new TreeNode(nodeName)))
    {
        ProcessNode(treeNode, rows);
        parent.Add(treeNode);            
    }
}


Now your function looks like this:

var index = ds.feat.Columns.IndexOf("name");
foreach (var treeNode in (
            from row in ds.feat.Rows,
            let nodeName = Convert.ToString(row[index])
            where rows.Contains(nodeName)
            select new TreeNode(nodeName)))
{
   ProcessNode(treeNode, ds);
}


This is a start.  I'm not happy with having to pass DataSet into the functions, but without fully understanding the data structure, I can't think of another way of doing it.