A "Component Moved on Canvas" event in Grasshopper

Hi there! I am looking for an event that fires when a pivot of a custom Grasshopper component changes its location on the canvas. I’ve tried the following events:

  • AttributesChanged - doesn’t fire
  • DisplayExpired - doesn’t fire
  • ObjectChanged - doesn’t fire
  • PreviewExpired - didn’t expect it to fire to begin with

I’ve also tried approaching this from the opposite direction by tapping into some events on the document and on the canvas:

  • doc.ContextChanged - doesn’t fire
  • doc.ModifiedChanged - not sure if relevant, but doesn’t fire
  • canvas.DragDrop - likely not relevant and doesn’t fire
  • canvas.Invalidated - fires way too often
  • canvas.Click - fires way too often
  • canvas.Move - doesn’t fire
  • canvas.LocationChanged - probably not relevant and doesn’t fire

I even tried inheriting from INotifyPropertyChanged, but obviously, the setter on the Pivot property doesn’t raise the PropertyChanged event, so this was a largely futile pursuit as well. Any thoughts?

1 Like

Create custom component attributes, override Pivot and raise an event in its setter.

1 Like

For anyone else who will find this helpful. Based on the combined wisdom from @andheum and @Dani_Abalde, this is what I ended up with (works perfectly):

Here is my custom ComponentAttributes class:

public class CustomComponentAttributes : GH_ComponentAttributes
    // Just to keep track of the old location (optional)
    public PointF LastKnownPivot { get; set; }

    public CustomComponentAttributes (IGH_Component comp) : base(comp)
        this.LastKnownPivot = new PointF(this.Pivot.X, this.Pivot.Y);

    public override PointF Pivot 
        get => base.Pivot;
            base.Pivot = value;
            // Raise custom event
            OnPivotMoved(new ComponentMovedEventArgs(

    // The custom event being raised from the Pivot setter
    public event EventHandler PivotMoved;
    public void OnPivotMoved(ComponentMovedEventArgs e)
        EventHandler handler = PivotMoved;
        handler?.Invoke(this, e);
        this.LastKnownPivot = new PointF(this.Pivot.X, this.Pivot.Y);

Here are my custom event arguments (they can be whatever you want them to be):

public class ComponentMovedEventArgs : EventArgs
    public Guid InstanceGuid { get; set; }
    public Guid ComponentGuid { get; set; }
    public PointF OldPivot { get; set; }
    public PointF NewPivot { get; set; }

    public ComponentMovedEventArgs(
        Guid instanceGuid, 
        Guid componentGuid, 
        PointF oldPivot,
        PointF newPivot)
        this.InstanceGuid = instanceGuid;
        this.ComponentGuid = componentGuid;
        this.NewPivot = newPivot;

And this is my custom component:

public class MyCustomComponent : GH_Component
    // Set custom attributes
    public override void CreateAttributes()
        Attributes = new CustomComponentAttributes(this);
        ((CustomComponentAttributes )Attributes).PivotMoved += CustomComponent_PivotMoved;

    private void CustomComponent_PivotMoved(object sender, EventArgs e)
        // Re-transmitting the event from inside the component itself
        ComponentMovedEventArgs args = e as ComponentMovedEventArgs;

    // Event exposed on the component itself
    public event EventHandler ComponentMoved;
    public void OnComponentMoved(ComponentMovedEventArgs e)
        EventHandler handler = ComponentMoved;
        handler?.Invoke(this, e);

So now I can just do this:

MyCustomComponentInstance.ComponentMoved += <SomeEventHandlerHere>

Thank you so much for the help!