I'd like to comment, but rep isn't high enough yet.
The accepted answer works great. However as mentioned the code doesn't trigger the PropertyValueChanged event.
Adding a call to OnPropertyValueChanged triggers the PropertyValueChanged event.
entry.PropertyDescriptor.SetValue(parent, !(bool)entry.Value);
this.Refresh();
base.OnPropertyValueChanged(null);
Then in the PropertyValueChanged event code you can access the custom object that has been changed.
To communicate the changed property back to the form create some properties in the custom object, with Browsable set to false so they do not appear in the PropertyGrid.
[Browsable(false)]
public string changedParent { get; set; }
[Browsable(false)]
public string changedLabel { get; set; }
[Browsable(false)]
public string changedValue { get; set; }
At the top of the Form class create this static property
public partial class Form1 : Form
{
private static Form1 form = null;
In the constructor of Form1 link form to this.
public Form1()
{
InitializeComponent();
..
..
form = this;
Back in grid_MouseClick before triggering OnPropertyValueChanged save off the changed property information.
entry.PropertyDescriptor.SetValue(parent, !(bool)entry.Value);
this.Refresh();
form.sh.changedParent = entry.Parent.Label;
form.sh.changedLabel = entry.Label;
form.sh.changedValue = entry.Value.ToString();
base.OnPropertyValueChanged(null);
Now in the PropertyValueChanged event code you can determine which property was changed.
form.customobject.changedParent
form.customobject.changedLabel
form.customobject.changedValue