I have a ContextMenu with MenuItems in it with their CheckOnClick property set to true.
And I want to save the Checked state of each MenuItem in the user.config file.

So what I did is bind the Checked property of the MenuItem to an application settings I created.
But when I click the MenuItem, it gets checked but the application setting value doesn't change.
A quote from an MSDN article comes to mind:

"You can only bind an application setting to a component that supports the IBindableComponent interface. Also, the component must implement a change event for a specific bound property, or notify application settings that the property has changed through the INotifyPropertyChanged interface. If the component does not implement IBindableComponent and you are binding through Visual Studio, the bound properties will be set the first time, but will not update. If the component implements IBindableComponent but does not support property change notifications, the binding will not update in the settings file when the property is changed."

Is it related to my issue?
How can I check if a control supports IBindableComponent ?
When I searched MenuItem in MSDN I got this under MenuItem Class (System.Windows.Controls) :
public class MenuItem : HeaderedItemsControl, ICommandSource
If IBindableComponent is not there does it mean that the control doesn't implement it?
And if indeed the aforementioned property cannot be bound to an application setting, what other alternatives do I have to achieve what I'm trying to do?

Thanks in advnance,
teatime.

Recommended Answers

All 7 Replies

Manually databind the property/control in code:

private void frmMiscTasks_Load(object sender, EventArgs e)
    {
      checkBox1.Checked = Properties.Settings.Default.SomeSetting;
    }

    private void frmMiscTasks_FormClosing(object sender, FormClosingEventArgs e)
    {
      Properties.Settings.Default.SomeSetting = checkBox1.Checked;
      Properties.Settings.Default.Save();
    }

>If IBindableComponent is not there does it mean that the control doesn't implement it?

Yes.

>And if indeed the aforementioned property cannot be bound to an application setting, what other alternatives do I have to achieve what I'm trying to do?

1. Follows the sknake's post #2. Manually databind the property/control in code.
2. Implements IBindableComponent interface.

Success! Thanks a lot guys!
I already thought of doing what sknake suggested, (not that I'm ungrateful for his response :)), but I thought it to be a little kludgy so I tried implementing the IBindableComponent interface and created a class like the one in the link adatapost posted.
At first I had trouble binding the custom control to the setting. I tried doing it with the editor, and then when that failed I tried doing it programmatically(is that the correct term?) in the code similar to what the person in that link did

this.menuItem1.DataBindings.Add("Checked", VGPlayer.Properties.Settings.Default.Vid_NormalSize, "Value))

, but that didn't work.
Then I saw the statement the code designer created to bind a different control and I used it, fitting it to my custom control:

this.menuItem1.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::VGPlayer.Properties.Settings.Default, "Vid_NormalSize", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));

That solved the problem :)
Incidentally the code, from that link, that I used to create the custom control with raised a few questions:

class BindableToolStripMenuItem : ToolStripMenuItem,IBindableComponent

    {
        #region IBindableComponent Members
        private BindingContext bindingContext;
        private ControlBindingsCollection dataBindings;

        [Browsable(false)]
        public BindingContext BindingContext
        {
            get
            {
                if (bindingContext == null)
                {
                    bindingContext = new BindingContext();
                }
                return bindingContext;

            }
            set
            {
                bindingContext = value;
            }
        }
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ControlBindingsCollection DataBindings
        {
            get
            {
                if (dataBindings == null)
                {
                    dataBindings = new ControlBindingsCollection(this);
                }
                return dataBindings;
            }
        }
        #endregion
    }

What are those statements in the square brackets and what are they used for?
They gave me errors when I tried running the code with them.
I'm a bit of a noob programmer and don't like to copy paste code without understanding it.

commented: thanks for sharing your solution +6

>What are those statements in the square brackets and what are they used for?

Attributes.

>What are those statements in the square brackets and what are they used for?

Attributes.

Cheers :)

Great post! I have mild animosity toward .NET binding which is why I posted what I did :P

You should probably add a constructor to initialize your binding context instead of doing it in the property.

using System.ComponentModel;
using System.Windows.Forms;

namespace daniweb
{
  public class BindableToolStripMenuItem : ToolStripMenuItem, IBindableComponent
  {
    private BindingContext bindingContext;
    private ControlBindingsCollection dataBindings;

    public BindableToolStripMenuItem()
      : base()
    {
      bindingContext = new BindingContext();
      dataBindings = new ControlBindingsCollection(this);
    }

    [Browsable(false)]
    public BindingContext BindingContext
    {
      get
      {
        return bindingContext;

      }
      set
      {
        bindingContext = value;
      }
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ControlBindingsCollection DataBindings
    {
      get
      {
        return dataBindings;
      }
    }
  }
}

Great post! I have mild animosity toward .NET binding which is why I posted what I did :P

You should probably add a constructor to initialize your binding context instead of doing it in the property.

using System.ComponentModel;
using System.Windows.Forms;

namespace daniweb
{
  public class BindableToolStripMenuItem : ToolStripMenuItem, IBindableComponent
  {
    private BindingContext bindingContext;
    private ControlBindingsCollection dataBindings;

    public BindableToolStripMenuItem()
      : base()
    {
      bindingContext = new BindingContext();
      dataBindings = new ControlBindingsCollection(this);
    }

    [Browsable(false)]
    public BindingContext BindingContext
    {
      get
      {
        return bindingContext;

      }
      set
      {
        bindingContext = value;
      }
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ControlBindingsCollection DataBindings
    {
      get
      {
        return dataBindings;
      }
    }
  }
}

What would be the difference?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.