Update Value List

Hello,
I looked at several topics related with updating value list, but I can’t seem to find a solution.
I want to update an existing value list connected to a C# component with a list input as in the attached Grasshopper file.
AutoValueList.gh (120.6 KB)

I’m using codes by James Ramsden, but I want to update the connected value list instead of creating a new one when a boolean button is clicked.

  private void RunScript(bool R, List<string> VL, List<string> L, ref object A)
  {

    if (R)
    {
      var valList = new Grasshopper.Kernel.Special.GH_ValueList();
      valList.CreateAttributes();
      valList.Name = "Feature Selections";
      valList.NickName = "Features";
      valList.ListMode = Grasshopper.Kernel.Special.GH_ValueListMode.DropDown;

      int inputCount = this.Component.Params.Input[1].SourceCount;
      valList.Attributes.Pivot = new PointF((float) this.Component.Attributes.DocObject.Attributes.Bounds.Left - valList.Attributes.Bounds.Width - 30,
        (float) this.Component.Params.Input[1].Attributes.Bounds.Y + inputCount * 30);

      valList.ListItems.Clear();

      for (int i = 0; i < L.Count; i++)
      {
        valList.ListItems.Add(new Grasshopper.Kernel.Special.GH_ValueListItem(L[i], i.ToString()));
      }
      valList.Description = "Select one out of " + L.Count.ToString() + " features to identify distinct panels.";

      GrasshopperDocument.AddObject(valList, false);

      this.Component.Params.Input[1].AddSource(valList);
    }
  }

I tried to add the following code, but it crashed Rhino.

valList.ExpireSolution(true);

Thanks for any help in advance!

If you change/update that value list component WHILE your c# script is running, because the value list component is connected to the c# script, it will trigger the c# to recompute again and again, a loop, and that is the crash.

You need to use a delayed method to do your edits after the script is done.
Search on this forum for grasshopper + “ScheduleSolution” and/or “SolutionCallback”.
I can’t give a more complete answer right now…

Thank you @maje90. I tried your suggestion after some research, but I don’t seem to understand it fully at the moment. I added the following code at the end of the previous code.

      Grasshopper.Kernel.GH_Document doc = this.Component.OnPingDocument();

      if (doc != null)
        doc.ScheduleSolution(100, SolutionCallback);

I also added the additional code below.

 // <Custom additional code> 
  private void SolutionCallback(GH_Document document)
  {
    var guid = this.Component.Params.Input[1].InstanceGuid;
    var comp = document.FindObject(guid, false);
    comp.ExpireSolution(false);
  }
  // </Custom additional code> 

It still creates new value list components, while I’m clicking the boolean button. I’ll dig into the forum more, but any comments will be helpful to speed up my slow progress.
Thank you again.

Try this:
AutoValueList.gh (8.6 KB)

 private void RunScript(bool R, string VL, List<string> options, List<string> values, ref object A)
  {
    // this check is to trigger this component only when the R button is RELEASED
    // so, when the SolutionCallback is executed, the main code here will be NOT executed
    if(R)oldstate = true;
    else if(!R && oldstate){
      oldstate = false;
      valList = (Grasshopper.Kernel.Special.GH_ValueList) this.Component.Params.Input[1].Sources[0];
      if(valList != null){
        opts = options;
        vals = values;
        this.GrasshopperDocument.ScheduleSolution(5, SolutionCallback);
      }
    }
  }

  // <Custom additional code> 
  public bool oldstate = false;
  public Grasshopper.Kernel.Special.GH_ValueList valList;
  public List<string> opts;
  public List<string> vals;
  private void SolutionCallback(GH_Document document){
    valList.ListItems.Clear();
    for (int i = 0; i < opts.Count; i++){
      valList.ListItems.Add(new Grasshopper.Kernel.Special.GH_ValueListItem(opts[i], vals[i]));
    }
    valList.ExpireSolution(true);
  }
1 Like

Awesome! Thank you so much for your quick help.