5

I have written a user control, MenuItem, which inherits from a Form Label.

I have a backgroundworker thread whose IsBusy property is exposed through a property in the MainForm as IsBackgroundBusy.

How do I read this property from the MenuItem usercontrol? I am currently using Application.UseWaitCursor and I set that in the backgroundworker and it works perfectly, however I do not want the cursor to change. That's why I figured a property that I could set would be much better.

Here is the code in my MainForm:

public partial class MainForm : Form
{
    public bool IsBackgroundBusy
    {
        get
        {
            return bwRefreshGalleries.IsBusy;
        }
    }

Here is the code for my usercontrol:

public partial class MenuItem: Label
{
    private bool _disableIfBusy = false;

    [Description("Change color if Application.UseWaitCursor is True")]
    public bool DisableIfBusy
    {
        get
        {
            return _disableIfBusy;
        }

        set
        {
            _disableIfBusy = value;
        }
    }

    public MenuItem()
    {
        InitializeComponent();
    }

    protected override void OnMouseEnter( EventArgs e )
    {
        if ( Application.UseWaitCursor && _disableIfBusy )
        {
            this.BackColor = SystemColors.ControlDark;
        }
        else
        {
            this.BackColor = SystemColors.Control;
        }

        base.OnMouseEnter( e );
    }
John Saunders
  • 160,644
  • 26
  • 247
  • 397
RoadRacer524
  • 53
  • 1
  • 4
  • Is the heart of your question how to [access form from usercontrol](http://stackoverflow.com/questions/14921354/access-form-from-usercontrol)? – ryanyuyu Jan 07 '15 at 20:18
  • Yes, I suppose it is. I know I can use an event in the form instead but I wanted to avoid that if at all possible for the sake of simplicity when reusing the control since many menu items will be created. – RoadRacer524 Jan 07 '15 at 20:22
  • @ryanyuyu That works as long as you don't mind locking the usercontrol to one type of form. More complicated would be to create a form interface and have the forms that use the control inherit from that. – Steve Wellens Jan 07 '15 at 20:22
  • @ryanyuyu I'm sorry, I just realized there was a link in your comment. I tried doing that as well but I couldn't declare a form as MainForm within my usercontrol. I tried to set a reference to the project but I couldn't because it would cause a circular dependency. – RoadRacer524 Jan 07 '15 at 20:28
  • Yeah, and since BackgroundWorkers were mentioned... that probably won't work too well. Well that explains why this is a separate question now. – ryanyuyu Jan 07 '15 at 20:31
  • 3
    You can always create an interface which exposes the `IsBackgroundBusy { get; }` property which is implemented by your `MainForm` and used by your `MenuItem`. This way your `MainForm` isn't coupled with your `MenuItem`. – Anthony Jan 07 '15 at 20:37
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jan 07 '15 at 23:48

1 Answers1

1

(Note: it's not clear to me whether you have an actual UserControl here or not. The MenuItem class you show inherits Label, not UserControl. You should probably avoid using the term "usercontrol" or "user control" when you are not actually dealing with a UserControl object).

Absent a complete code example, it's hard to know exactly what the right solution here is. However, assuming you are using the BackgroundWorker in a typical fashion, then you simply need for the owner of the control (i.e. the containing Form) to pass the necessary state to the control as it changes. E.g.:

class MenuItem : Label
{
    public bool IsParentBusy { get; set; }
}

// I.e. some method where you are handling the BackgroundWorker
void button1_Click(object sender, EventArgs e)
{
    // ...some other initialization...

    bwRefreshGalleries.RunWorkerCompleted += (sender1, e1) =>
    {
        menuItem1.IsParentBusy = false;
    };

    menuItem1.ParentIsBusy = true;
    bwRefreshGalleries.RunAsync();
}

If you already have a handler for the RunWorkerCompleted event, then just put the statement to set the IsParentBusy property there instead of adding another handler.

Then instead of using the Application.UseWaitCursor property, you can just look at the IsParentBusy property.

There are other mechanisms you could use; I do agree with the general sentiment that the MenuItem control should not be tied to your specific Form sub-class. If for some reason the above doesn't work in your case, you need to elaborate on your question: provide a good code example and explain exactly why simply having the container of the control manage its state directly doesn't work for you

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thank you for clarifying the terminology I should use to properly describe my question and also for your answer. It accomplishes exactly what I want just in a different method which I didn't consider. However, I'm getting an error when setting (sender, e). Cannot be declared in this scope because it would give a different meaning to 'sender'. But what you're pointing out is perfect if I can get it to work. – RoadRacer524 Jan 08 '15 at 14:16
  • I was drowning in a puddle. I declared a 'new' sender and eventargs (s, i) and it works perfectly. Thank you @Peter! – RoadRacer524 Jan 08 '15 at 14:39
  • Happy to help. Sorry for the typo...I will edit the post to fix that, in case someone else is looking for a similar solution. Glad you were able to figure out my mistake on your own. :) – Peter Duniho Jan 08 '15 at 18:17