none
Why is predicate misinterpreting parameters' values when called in recursive function RRS feed

  • Question

  • 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.

    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);
    }

    Monday, April 8, 2019 11:23 AM

All replies

  • 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


    Monday, April 8, 2019 4:21 PM
  • Hi Etienne Yamsi,

    Thanks for your sharing.

    Please mark the solution as answer. This will make answer searching easier in the forum and be beneficial to community members as well.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, April 9, 2019 4:21 AM
    Moderator