12 Replies - 701 Views - Last Post: 26 January 2011 - 08:22 AM Rate Topic: -----

#1 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

How can I create a custom event?

Posted 25 January 2011 - 05:11 PM

I have a custom set of UserControls: NavigationBar and NavigationItem.

I'd like that whenever the user clicks anywhere in the NavigationItem, an event is fired. I don't know how to set this up.
Posted Image


I've tried this:

public partial class NavigationBar : UserControl
{
    public NavigationBar()
    {
        InitializeComponent();
        SetupEvents();
    }

    public List<NavigationItem> NavigationItems { private get; set; }
    public NavigationItem SelectedItem { get; set; }

    private void SetupEvents()
    {
        navigationItem1.Click += new EventHandler(navigationItemClick);
    }

    void navigationItemClick(object sender, EventArgs e)
    {
        MessageBox.Show("Clicked on " + sender.ToString());
    }
}



But that event only fires when the user specifically clicks on the NavigationItem control, but not when he clicks on the picture or text. (Those are PictureBox and Label).

What would be the best course of action? I'd like to create something well, not hacky code. Thanks!

Is This A Good Question/Topic? 0
  • +

Replies To: How can I create a custom event?

#2 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4461
  • View blog
  • Posts: 7,771
  • Joined: 08-June 10

Re: How can I create a custom event?

Posted 25 January 2011 - 05:42 PM

Do those pictures and labels reside in the NavigationItem control? If so, I'd put an event on NavigationItem. Have it triggered on MouseUp for each control contained in the NavigationItem. Then in your NavigationBar, you can subscribe like you're doing.
Was This Post Helpful? 2
  • +
  • -

#3 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 25 January 2011 - 06:04 PM

Thanks, that solved it:

public partial class NavigationBar : UserControl
{
    public NavigationBar()
    {
        InitializeComponent();
    }

    public List<NavigationItem> NavigationItems { private get; set; }
    public NavigationItem SelectedItem { get; set; }
}

public partial class NavigationItem : UserControl
{
    public NavigationItem()
    {
        InitializeComponent();        
    }

    private bool _isSelected = false;
    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            _isSelected = value;
            if (_isSelected)
                lblDisplayText.BackColor = Customizationhelper.GetSecondaryColor();
            else
                lblDisplayText.BackColor = Customizationhelper.GetPrimaryColor();
        }
    }

    private Image _picture = null;
    public Image Picture
    {
        get
        {
            return _picture;
        }
        set
        {
            _picture = value;
            ptbIcon.Image = _picture;
        }
    }

    private string _content = null;
    public string Content 
    {
        get
        {
            return _content;
        }
        set
        {
            _content = value;
            lblDisplayText.Text = _content;
        }
    }

    private void ptbIcon_MouseUp(object sender, MouseEventArgs e)
    {
        IsSelected = true;
    }

    private void lblDisplayText_MouseUp(object sender, MouseEventArgs e)
    {
        IsSelected = true;
    }

    private void NavigationItem_MouseUp(object sender, MouseEventArgs e)
    {
        IsSelected = true;
    }
}


I could create a single handler for all three items, but that would be spending effort in the same way, just somewhere else.

I have another related question now.

This is working fine now, except when I click on a second NavigationItem, I'd like the other items to have .IsSelected set to false. This would automatically change colors.

Currently they stay selected.
Posted Image


Any ideas how to approach this?

This post has been edited by Sergio Tapia: 25 January 2011 - 06:08 PM

Was This Post Helpful? 0
  • +
  • -

#4 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 25 January 2011 - 06:26 PM

Just had this idea pop in:


public partial class NavigationBar : UserControl
{
    public NavigationBar()
    {
        InitializeComponent();
    }

    public List<NavigationItem> NavigationItems { private get; set; }
    public NavigationItem SelectedItem { get; set; }

    public void RefreshSelectedDisplay()
    {
        //All control in this bar are NavigationItems.
        foreach (var c in this.Controls)
        {
            if (!((NavigationItem)c).IsSelected)
            {
                ((NavigationItem)c).IsSelected = false;
            }
        }
    }
}



If I could just somehow call this method from within my NavigationItem.cs class, the world would be green again. :P

But maybe I'm doing this the wrong way. Teach me! :D
Was This Post Helpful? 0
  • +
  • -

#5 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5475
  • View blog
  • Posts: 11,759
  • Joined: 02-June 10

Re: How can I create a custom event?

Posted 25 January 2011 - 06:47 PM

Quote

I'd like that whenever the user clicks anywhere in the NavigationItem, an event is fired. I don't know how to set this up.

I think I'd go a slightly different direction. Your NaviagationBar and NavigationItem both inherit from UserControl. UserControl already has a Click event, so you don't really need to make any custom event.

You just need NavigationBar to subscribe to the .Click event of each NavigationItem.
You also reverse subscribe that relationship and have each NavigationItem subscribe to the .Click event from NavigationBar.

So here's what happens...
  • NavigationItem1 gets clicked by the user
  • It raises the .Click event with Navigation1 as the 'sender' object of the event.
  • NavigationBar hears that event and in it's handler for that event raises it's own .Click event as if it was clicked on but when it does so it passes along the received sender object instead of itself. It just relays the sender up the food chain.
  • All of the NavigationItems are subscribed to the NavigationBar's .Click event so they all hear that event. In the NavigationItem's handler for the NavigationBar.Click event you check to see who the sender is. If sender != this, then clear the highlight. All of the NavigationItems except the one that originated the first click event will clear themselves.
  • Any external controls other than the NavigationItems that are also subscribed to the NavigationBar.Click event will also hear the Click event when it is raised and they will receive the specific NavigationItem1 object that was originally clicked on by the user. So any listener will get the 'Alumnos' object, or 'Libretos' object that was clicked on. Do any kind of comparison or processing you need to from within the receiving class.

All of the objects are 'black boxed' from each other and can react independently based solely on the 'sender' object that is received through the click event.

So you just need for that sender to have some meaningful information. It is an object after all and therefore can be as complex as you need it to be. Or you might be able to just use a simple property like the Type or the Text of the object. That's really all up to you.
Was This Post Helpful? 2
  • +
  • -

#6 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 25 January 2011 - 06:52 PM

Thanks a bunch for taking the time to help me and teach me a thing or two.

I'll process what you suggested and see what I can come up with. Can you elaborate with code how I would accomplish this:

Quote

You just need NavigationBar to subscribe to the .Click event of each NavigationItem.

Was This Post Helpful? 0
  • +
  • -

#7 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5475
  • View blog
  • Posts: 11,759
  • Joined: 02-June 10

Re: How can I create a custom event?

Posted 25 January 2011 - 07:12 PM

View PostSergio Tapia, on 25 January 2011 - 06:52 PM, said:

Thanks a bunch for taking the time to help me and teach me a thing or two.

I'll process what you suggested and see what I can come up with. Can you elaborate with code how I would accomplish this:

Quote

You just need NavigationBar to subscribe to the .Click event of each NavigationItem.


I was thinking the exact same thing as I was doing the dishes. Check back here in an hour. I should have a Solution file for you to download.
Was This Post Helpful? 1
  • +
  • -

#8 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 25 January 2011 - 07:36 PM

Thanks a bunch for your help. :)
Was This Post Helpful? 0
  • +
  • -

#9 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5475
  • View blog
  • Posts: 11,759
  • Joined: 02-June 10

Re: How can I create a custom event?

Posted 25 January 2011 - 09:21 PM

This could practically be a Tutorial by now. <laugh>



The Solution SergNave contains two projects.
  • SergCntrlLib - a Windows Forms Control library
    • NavItem
      • 150x40 Usercontrol with a docked panel
        • textbox
        • picturebox

    • StudentNavBar

  • SergNave - A Windows forms application for testing the library controls


The NavItem has properties redirecting Text, Image and BackColor to the right sub-controls. Meaning if you set NavItem.Text it sets the label text. If you set NavItem.Image it sets the PictureBox.Image
Click events from the panel, picturebox and textbox all feed to the same method that raises the NavItem.Click event.

The StudentNavBar contains 3 NavItems. When StudentNavBar loads it wires up the events
        private void StudentNavBar_Load(object sender, EventArgs e)
        {
            //Wire all my children to the same handler
            foreach (var c in this.Controls)
            {
                ((NavItem)c).Click += NavItem_Click;
            }

            //Wire my click to all my children's handler
            foreach (var c in this.Controls)
            {
                this.Click += ((NavItem)c).Parent_Click;
            }
        }



When a child NavItem is clicked the NavItem_Click method handles it. (see the subscription in line 06 above). That method causes the StudentNavBar to raise its own Click event but sends the originating child control as the sender.
        void NavItem_Click(object sender, EventArgs e)
        {
            RaiseClick(sender); // Pass the child along up the food chain
        }


        void RaiseClick(object OriginalSender)
        {
            EventHandler handler = Click;
            if (handler != null)
            {
                handler(OriginalSender, EventArgs.Empty);
            }
        }


Looking back at the first code block line 12 we see that we also wired the StudentNavBar click event to each child's Parent_Click event handler method. All three children will run this method, and the one that originated this chain will NOT revert its backcolor
        public void Parent_Click(object sender, EventArgs e)
        {
            if (sender != this)
            {

                this.BackColor = PreviousColor;
            }
        }



The test program has one StudentNavBar and one label. We wired the Click event of the StudenNavBar to a handler that displays the original sender name on the label.
Attached Image
        private void studentNavBar1_Click(object sender, EventArgs e)
        {
            label1.Text = sender.ToString();
        }


That's the short version of the explanation. The entire Visual Studio 2010 solution is zipped and attached. For those that don't trust .zip projects from unknown sources, I'll post all the primary code below.

SergeCntrlLib - NavItem
Spoiler


SergCntrlLib - StudentNavBar
Spoiler


SergeNave - Test Program
Spoiler
Attached File  SergNave.zip (212.02K)
Number of downloads: 35
Was This Post Helpful? 2
  • +
  • -

#10 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 26 January 2011 - 07:06 AM

A thousand upvotes for you man! Thanks so much for taking the time to help a stranger. I'm going to dissect this and learn a lot I think. :)

By the way, last night I had a dream where I tried to solve this and this morning I woke up and had the idea of using the INotifyPropertyChanged interface to 'listen in' when a NavigationItem has it's selection property changed.

Would this work!? :lol: I'll post back with results.

Again, thanks so much.
Was This Post Helpful? 0
  • +
  • -

#11 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5475
  • View blog
  • Posts: 11,759
  • Joined: 02-June 10

Re: How can I create a custom event?

Posted 26 January 2011 - 07:22 AM

View PostSergio Tapia, on 26 January 2011 - 07:06 AM, said:

A thousand upvotes for you man! Thanks so much for taking the time to help a stranger. I'm going to dissect this and learn a lot I think. :)

By the way, last night I had a dream where I tried to solve this and this morning I woke up and had the idea of using the INotifyPropertyChanged interface to 'listen in' when a NavigationItem has it's selection property changed.

Would this work!? :lol: I'll post back with results.

Again, thanks so much.


Anyone who has read my cookbook will tell you 'There's more than one way to skin a cat'. Would it work? I'm sure it could be made to work. But does it seem like the straightforward way to do it? I mean do you listen for a button to change it's .Selected property in order to know the user clicked on it? .Selected is not .Clicked. Sure it might do for this control. But can you make a personal standard out of it? What happens in 3 months when you make a different custom control and you need to treat .Selected separately from .Clicked? You'll notice that in my solution we only use .Click events to handle being clicked on. That seems straightforward to me. And when you are coding in a workplace where others have to deal with your code as well it helps if things are straightforward.
Was This Post Helpful? 0
  • +
  • -

#12 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: How can I create a custom event?

Posted 26 January 2011 - 08:17 AM

Ok, came back to confirm that this fits 100% with what I was going for. Thanks a lot for your help! :)

The controls wrap everything up nicely and in the future if I need a control I can just use this.

Here's what it looks like from the outside:

private void navigationBar1_Click(object sender, EventArgs e)
{
    MessageBox.Show(sender.ToString());
}



This is awesome. :D
Posted Image

This post has been edited by Sergio Tapia: 26 January 2011 - 08:19 AM

Was This Post Helpful? 0
  • +
  • -

#13 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5475
  • View blog
  • Posts: 11,759
  • Joined: 02-June 10

Re: How can I create a custom event?

Posted 26 January 2011 - 08:22 AM

View PostSergio Tapia, on 26 January 2011 - 08:17 AM, said:

Ok, came back to confirm that this fits 100% with what I was going for. Thanks a lot for your help! :)

The controls wrap everything up nicely and in the future if I need a control I can just use this.

Glad to help.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1