Click here to Skip to main content
14,327,298 members
Rate this:
Please Sign up or sign in to vote.
See more:
I'm trying to create a extended treeview control inheriting from the existing winform TreeView control. Created a Load() function in the class TreeViewEx. In this function the dataSource is looped in a foreach. This foreach then calls the Where() extension method on the looping dataSource passing to it a methode (which takes as parameter the current element) returning a predicate. This predicate misintepretes the parameter value passed to it. It seems to be using previous parameter values.

value of arg in method before returning predicate => Image[^]

value of arg when debugger enters predicate => Image[^]

What I have tried:

Initially i thought this behavior was due to the fact that i am iterating through an Enumerable not a list, so i change the different enumerables to List but nothing changed. Also tried to instatiate the returned predicate but nothing.

Load function :


public Func<T, Func<T, bool>> GetChildrenPredicate { get; set; }
.
.
.
public virtual void Load(List<T> dataSource = null)
{
    try
    {
        if (CreateNode == null)
        {
            OnError?.Invoke(this, new ArgumentNullException("CreateNode"));
            return;
        }
        if (GetParentKey == null)
        {
            OnError?.Invoke(this, new ArgumentNullException("GetParentKey"));
            return;
        }
        if (GetChildrenPredicate == null)
        {
            OnError?.Invoke(this, new ArgumentNullException("GetChildrenPredicate"));
            return;
        }

        var finalDataSource = dataSource ?? DataSource;

        TreeNode node = null;
        BeginUpdate();
        foreach (var item in finalDataSource)
        {
            node = CreateNode(item);
            node.Tag = item;

            if (this.Nodes.Find(node.Name, true).Count() == 0)
            {
                var n = this.Nodes.Find(this.GetParentKey(item), true).FirstOrDefault() as TreeNode;

                if (n == null)
                {
                    this.Nodes.Add(node);
                }
                else
                {
                    n.Nodes.Add(node);
                }

                List<T> children = finalDataSource
                                  .ToList()                                   
                                  .Where(this.GetChildrenPredicate(item))
                                  .ToList(); //this.GetChildrenPredicate is
                                //the property func generating the 
                                //predicate set by a different class

                if (children.Count() > 0)
                {
                    // Recursively call this function for all childRows
                    Load(children);
                }

            }
        }
        EndUpdate();
    }
    catch (Exception ex)
    {
        OnError?.Invoke(this, ex);
    }
}


GetChildrenPredicate :

private Func<ORM.DataModels.Menu, bool> GetChildrenPredicate(ORM.DataModels.Menu arg)
{

    return (ORM.DataModels.Menu m) =>
    (m.Lepere == arg.Codmen) ||
    (m.Lepere == null && arg.Codmen == "_" + m.Niveau);
}
Posted
Updated 8-Apr-19 6:19am
Comments
Gerry Schmitz 8-Apr-19 10:06am
   
I build my own custom treeviews (WPF, UWP) using a sorted list of items, a listview, a level #, and about 30 lines of spaced code.

I would say yours is over-engineered; assuming it ever works and can be maintained.
bugMaker-237 8-Apr-19 10:28am
   
My treeview is in winform and is generic. So it relies on exteranl methods and events set by the controller. If you think it can be ameliorated i am opened to any suggestion.

1 solution

Rate this:
Please Sign up or sign in to vote.

Solution 1

Ok. I found the solution. Actually i did not realized that `finalDataSource` was overriden on each call of `Load()`. I was only focused on the weird behaviour of the predicate. just had to used the global DataSource property defined in the class.


List<T> children = this.DataSource.Where(this.GetChildrenPredicate(item)); //<= changed local variable finalDataSource to the defined property this.DataSource
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100