TheSwamp

Code Red => .NET => Topic started by: latour_g on May 13, 2013, 10:07:50 AM

Title: How to call a combobox
Post by: latour_g on May 13, 2013, 10:07:50 AM
Hi,
I'm searching a way to do something.  Here is what I have : buttons in front of combobox.  When I click on a button, the corresponding combobox goes in front of the button.
The thing is that I will have a lot of button+combobox so I want to do a general function.  Here is what I have :

Code: [Select]
private void btnTuyaux_MouseDown(object sender, MouseEventArgs e)
{   
     cboTuyaux.Enabled = true;
     cboTuyaux.Visible = true;
     cboTuyaux.BringToFront();
     cboTuyaux.DroppedDown = true;
     cboTuyaux.Focus();
}

 private void btnLigne_MouseDown(object sender, MouseEventArgs e)
{   
     cboLigne.Enabled = true;
     cboLigne.Visible = true;
     cboLigne.BringToFront();
     cboLigne.DroppedDown = true;
     cboLigne.Focus();
}

 private void btnBloc_MouseDown(object sender, MouseEventArgs e)
{   
     cboBloc.Enabled = true;
     cboBloc.Visible = true;
     cboBloc.BringToFront();
     cboBloc.DroppedDown = true;
     cboBloc.Focus();
}

 private void btnRaccord_MouseDown(object sender, MouseEventArgs e)
{   
     cboRaccord.Enabled = true;
     cboRaccord.Visible = true;
     cboRaccord.BringToFront();
     cboRaccord.DroppedDown = true;
     cboRaccord.Focus();
}

This is what I would want :

Code: [Select]
private void btnALL_MouseDown(object sender, MouseEventArgs e)
{   
     cboAll.Enabled = true;
     cboAll.Visible = true;
     cboAll.BringToFront();
     cboAll.DroppedDown = true;
     cboAll.Focus();
}

Is there a way to tell the program ''cboAll = the actual comboBox" ?

The button and the comboBox always have the save name (except for the beginning (btn and cb).
In my image, you see the buttons and the combobox are behing them.  For the moment I only 4 but I will have a lot more.

Thank you !
 8-)
Title: Re: How to call a combobox
Post by: nekitip on May 13, 2013, 10:23:15 AM
Unfortunatly, I will not give you an anwser, but maybe an advice.
Look into WPF. Try to buy some quick start book, and you will see that you can easily build your own control. In that way, once you have it, you will not need to have two overlaping controls but single one that will consist of button and a combobox (or something better), and its own independent logic.
Just give it a try.

And as for the quick help right now, I'm sure someone will help you.

Title: Re: How to call a combobox
Post by: WILL HATCH on May 13, 2013, 11:24:46 AM
I would try to make a custom class that holds the pair together.  Then they are very easily linked as the button's parent is your custom object and it has another child - your combo box
Title: Re: How to call a combobox
Post by: Micaletti on May 13, 2013, 01:13:25 PM
Code - vb.net: [Select]
  1. Public Class Form1
  2.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  3.         For Each Control In Me.Controls
  4.             If TypeOf Control Is Button Then
  5.                 Dim Button As Button = Control
  6.                 AddHandler Button.Click, AddressOf Button_Click
  7.             End If
  8.         Next
  9.     End Sub
  10.     Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
  11.         For Each Control In Me.Controls
  12.             If TypeOf Control Is ComboBox Then
  13.                 Dim ComboBox As ComboBox = Control
  14.                 If ComboBox.Name.Contains(sender.Name) Then
  15.                     ComboBox.Enabled = True
  16.                     ComboBox.Visible = True
  17.                     ComboBox.BringToFront()
  18.                     ComboBox.DroppedDown = True
  19.                     ComboBox.Focus()
  20.                     Exit For
  21.                 End If
  22.             End If
  23.         Next
  24.     End Sub
  25. End Class

Of course you would need to use an appropriate naming theme. This is not optimal but it gets the job done quickly. I would probably go with Will's solution. HTH.
Title: Re: How to call a combobox
Post by: latour_g on May 13, 2013, 01:44:27 PM
Thank you all ! I will check how to make a custom class, I would use it often.
Thanks Micaletti for your code, I'm goint to use this solution meanwhile.
 
Title: Re: How to call a combobox
Post by: TheMaster on May 13, 2013, 03:18:20 PM
Thank you all ! I will check how to make a custom class, I would use it often.
Thanks Micaletti for your code, I'm goint to use this solution meanwhile.

The VB code shown above has to do a lot of work needlessly each time a button is clicked.

While a custom class in WinForms, or data-binding and triggers would be the best way to solve your problem, a quick/dirty solution in WinForms would be to store the ComboBox in the Tag property of one or more buttons (when the form loads), and when a button is clicked, it's Tag property is the associated ComboBox, which you can cast to that type and use without having to look for it. That allows you to use a single event handler for all the buttons, since it isn't coupled to any specific Button or ComboBox (by using the event handler's Sender parameter to access the button that was clicked).

Title: Re: How to call a combobox
Post by: WILL HATCH on May 13, 2013, 05:44:23 PM
Thank you all ! I will check how to make a custom class, I would use it often.
Thanks Micaletti for your code, I'm goint to use this solution meanwhile.

The VB code shown above has to do a lot of work needlessly each time a button is clicked.

While a custom class in WinForms, or data-binding and triggers would be the best way to solve your problem, a quick/dirty solution in WinForms would be to store the ComboBox in the Tag property of one or more buttons (when the form loads), and when a button is clicked, it's Tag property is the associated ComboBox, which you can cast to that type and use without having to look for it. That allows you to use a single event handler for all the buttons, since it isn't coupled to any specific Button or ComboBox (by using the event handler's Sender parameter to access the button that was clicked).

*face palm* forgot about that sort of option.  Thanks!
Title: Re: How to call a combobox
Post by: Micaletti on May 13, 2013, 07:05:01 PM
I quickly threw together Tony's idea. Adding handlers and setting tags like this is not optimal either if you have other controls, but you get the idea.

Code - vb.net: [Select]
  1.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  2.         For Each Control In Me.Controls
  3.             If TypeOf Control Is Button Then
  4.                 Dim Button As Button = Control
  5.                 AddHandler Button.Click, AddressOf Button_Click
  6.                 For Each Item In Me.Controls
  7.                     If TypeOf Item Is ComboBox Then
  8.                         Dim ComboBox As ComboBox = Item
  9.                         If ComboBox.Name.Contains(Button.Name) Then
  10.                             Button.Tag = ComboBox
  11.                             Exit For
  12.                         End If
  13.                     End If
  14.                 Next
  15.             End If
  16.         Next
  17.     End Sub
  18.     Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)      
  19.         sender.Tag.Enabled = True
  20.         sender.Tag.Visible = True
  21.         sender.Tag.BringToFront()
  22.         sender.Tag.DroppedDown = True
  23.         sender.Tag.Focus()    
  24.     End Sub
Title: Re: How to call a combobox
Post by: TheMaster on May 13, 2013, 11:09:00 PM
I quickly threw together Tony's idea. Adding handlers and setting tags like this is not optimal either if you have other controls, but you get the idea.

Code - vb.net: [Select]
  1.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  2.         For Each Control In Me.Controls
  3.             If TypeOf Control Is Button Then
  4.                 Dim Button As Button = Control
  5.                 AddHandler Button.Click, AddressOf Button_Click
  6.                 For Each Item In Me.Controls
  7.                     If TypeOf Item Is ComboBox Then
  8.                         Dim ComboBox As ComboBox = Item
  9.                         If ComboBox.Name.Contains(Button.Name) Then
  10.                             Button.Tag = ComboBox
  11.                             Exit For
  12.                         End If
  13.                     End If
  14.                 Next
  15.             End If
  16.         Next
  17.     End Sub
  18.     Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)      
  19.         sender.Tag.Enabled = True
  20.         sender.Tag.Visible = True
  21.         sender.Tag.BringToFront()
  22.         sender.Tag.DroppedDown = True
  23.         sender.Tag.Focus()    
  24.     End Sub

If you don't mind, let's call the above your interpretation of how my idea would be implemented, but it's nothing like how I would do it, because it's wasteful to iterate over every control on the form many times, once for each button. Your interpretation also tests to see if the entire name of a button is contained in the name of a ComboBox, which according to the OP's description, won't work because the button names start with 'btn', and the combobox names start with 'cb'. You also have to cast the Tag property to a ComboBox (and not assume that the value is assigned to a ComboBox) before you can use it as one.

Here is how I might approach the problem (in C#):

Code - C#: [Select]
  1.  
  2.    public partial class Form1 : Form
  3.    {
  4.       public Form1()
  5.       {
  6.          InitializeComponent();
  7.       }
  8.  
  9.       /// Assumes that all buttons have names
  10.       /// starting with 'btn' and all combos
  11.       /// have names starting with 'cb'. What
  12.       /// follows those two prefixes in each
  13.       /// control's name is the association key.
  14.      
  15.       protected override void OnLoad( EventArgs e )
  16.       {
  17.          var items = this.Controls.OfType<ComboBox>()
  18.             .ToDictionary( c => c.Name.Substring( 2 ) );
  19.  
  20.          foreach( Button btn in this.Controls.OfType<Button>() )
  21.          {
  22.             string key = btn.Name.Substring( 3 );
  23.             ComboBox cb = null;
  24.             if( items.TryGetValue( key, out cb ) )
  25.             {
  26.                btn.Tag = cb;
  27.                btn.Click += OnButtonClick;
  28.             }
  29.          }
  30.  
  31.          base.OnLoad( e );
  32.       }
  33.  
  34.       void OnButtonClick( object Sender, EventArgs e )
  35.       {
  36.          Button btn = Sender as Button;
  37.          if( btn != null )
  38.          {
  39.             ComboBox cb = btn.Tag as ComboBox;
  40.             if( cb != null )
  41.             {
  42.                // TODO: Update combobox
  43.             }
  44.          }
  45.       }
  46.    }
  47.  

You might also note that the above code doesn't handle the Form's Load event, because it is internal to the form itself, so it overrides the corresponding virtual method (OnLoad), which is how you are supposed to hook into events from within the class that exposes them (or from a derived class). Public events are intended for use by external users of a class, not by derived types. In a properly-designed class each public event has a corresponding protected virtual method that can be overridden in a derived type to handle the notification without having to add/remove event handlers.
Title: Re: How to call a combobox
Post by: TheMaster on May 13, 2013, 11:43:17 PM
I would try to make a custom class that holds the pair together.  Then they are very easily linked as the button's parent is your custom object and it has another child - your combo box

Here's an example:

Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Forms;
  6. using System.ComponentModel;
  7.  
  8. namespace MyControls
  9. {
  10.  
  11.    /// A Button that has a reference to a ComboBox, that
  12.    /// can be set in the designer, eliminating the need
  13.    /// to search for implied associations between the
  14.    /// linked controls using their names:
  15.    
  16.    /// Using this on a form, select the LinkedButton,
  17.    /// and in the Properties pane you will see a property
  18.    /// named "LinkedComboBox", which can be set to an
  19.    /// existing ComboBox on the same form.
  20.    
  21.    public class LinkedButton : Button
  22.    {
  23.       public LinkedButton()
  24.       {
  25.       }
  26.  
  27.       [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )]
  28.       public ComboBox LinkedComboBox
  29.       {
  30.          get;set;
  31.       }
  32.  
  33.       protected override void OnClick( EventArgs e )
  34.       {
  35.          if( LinkedComboBox != null )
  36.          {
  37.             LinkedComboBox.Visible = true;
  38.             LinkedComboBox.BringToFront();
  39.             LinkedComboBox.Focus();
  40.             /// blah blah blah....
  41.          }
  42.          base.OnClick( e );
  43.       }
  44.    }
  45. }
  46.  
  47.  
Title: Re: How to call a combobox
Post by: Micaletti on May 14, 2013, 01:50:37 AM
Quote
If you don't mind, let's call the above your interpretation of how my idea would be implemented, but it's nothing like how I would do it, because it's wasteful to iterate over every control on the form many times, once for each button. Your interpretation also tests to see if the entire name of a button is contained in the name of a ComboBox, which according to the OP's description, won't work because the button names start with 'btn', and the combobox names start with 'cb'. You also have to cast the Tag property to a ComboBox (and not assume that the value is assigned to a ComboBox) before you can use it as one.

Call it whatever you want. Really all I was trying to convey to the OP about your idea was Button.Tag = Combobox... Button.Tag.Visible = True, which was your idea but you provided no code. Also you are assuming the tag on a button could be someting other than a combo box. You most certainly do not "have to" cast it to a combo box if thats all youre using the tags for. Furthermore I stated that he would have to use an appropriate naming theme for my code to work. He gets the point. I trust he can use string functions to suit his specific needs.

I predicted you wouldn't like either example which is why I specifically stated that they were not optimal. Clearly the OP is novice (so am I) or he wouldnt be asking such a question. He just needed some code to get his gears turning. I also pointed out that a custom class would be the "correct" way to do things.

Pointing out the obvious (restating what I have already said even), can be misinterpreted as something else. There is no need to check if the combobox is null in your last example, because you wouldnt create an instance of the class if it was. Anyone can nitpick example code, but it's not always welcome or necessary.
Title: Re: How to call a combobox
Post by: WILL HATCH on May 14, 2013, 10:40:29 AM
Quote
If you don't mind, let's call the above your interpretation of how my idea would be implemented, but it's nothing like how I would do it, because it's wasteful to iterate over every control on the form many times, once for each button. Your interpretation also tests to see if the entire name of a button is contained in the name of a ComboBox, which according to the OP's description, won't work because the button names start with 'btn', and the combobox names start with 'cb'. You also have to cast the Tag property to a ComboBox (and not assume that the value is assigned to a ComboBox) before you can use it as one.

Call it whatever you want. Really all I was trying to convey to the OP about your idea was Button.Tag = Combobox... Button.Tag.Visible = True, which was your idea but you provided no code. Also you are assuming the tag on a button could be someting other than a combo box. You most certainly do not "have to" cast it to a combo box if thats all youre using the tags for. Furthermore I stated that he would have to use an appropriate naming theme for my code to work. He gets the point. I trust he can use string functions to suit his specific needs.

I predicted you wouldn't like either example which is why I specifically stated that they were not optimal. Clearly the OP is novice (so am I) or he wouldnt be asking such a question. He just needed some code to get his gears turning. I also pointed out that a custom class would be the "correct" way to do things.

Pointing out the obvious (restating what I have already said even), can be misinterpreted as something else. There is no need to check if the combobox is null in your last example, because you wouldnt create an instance of the class if it was. Anyone can nitpick example code, but it's not always welcome or necessary.


:lol:  I think "thanks for pointing that out, my algorithms frequently use needless iteration to support my novice understanding of programming. I will keep this in mind moving forward" would have sufficed.

BTW if the combo box happens to be null the form will crash. After reading Tony's code for a little over a year I'm getting used to the way he makes sure that background tasks are bullet proof.
Title: Re: How to call a combobox
Post by: Micaletti on May 14, 2013, 10:51:19 AM
:lol:  I think "thanks for pointing that out, my algorithms frequently use needless iteration to support my novice understanding of programming. I will keep this in mind moving forward" would have sufficed.

BTW if the combo box happens to be null the form will crash. After reading Tony's code for a little over a year I'm getting used to the way he makes sure that background tasks are bullet proof.

That's cute Will, however:

Quote
This is not optimal but it gets the job done quickly.

I pointed that out. It was merely to show the OP that you can handle multiple events with a single method. I'm not going to get into a mouse wagging contest with you gentlemen because a) I would proudly lose, and b) I think we all agree that a custom control would be the ideal solution.
Title: Re: How to call a combobox
Post by: WILL HATCH on May 14, 2013, 12:01:49 PM
I would try to make a custom class that holds the pair together.  Then they are very easily linked as the button's parent is your custom object and it has another child - your combo box

Here's an example:

Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Forms;
  6. using System.ComponentModel;
  7.  
  8. namespace MyControls
  9. {
  10.  
  11.    /// A Button that has a reference to a ComboBox, that
  12.    /// can be set in the designer, eliminating the need
  13.    /// to search for implied associations between the
  14.    /// linked controls using their names:
  15.    
  16.    /// Using this on a form, select the LinkedButton,
  17.    /// and in the Properties pane you will see a property
  18.    /// named "LinkedComboBox", which can be set to an
  19.    /// existing ComboBox on the same form.
  20.    
  21.    public class LinkedButton : Button
  22.    {
  23.       public LinkedButton()
  24.       {
  25.       }
  26.  
  27.       [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )]
  28.       public ComboBox LinkedComboBox
  29.       {
  30.          get;set;
  31.       }
  32.  
  33.       protected override void OnClick( EventArgs e )
  34.       {
  35.          if( LinkedComboBox != null )
  36.          {
  37.             LinkedComboBox.Visible = true;
  38.             LinkedComboBox.BringToFront();
  39.             LinkedComboBox.Focus();
  40.             /// blah blah blah....
  41.          }
  42.          base.OnClick( e );
  43.       }
  44.    }
  45. }
  46.  
  47.  

What is the purpose of [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )] (http://msdn.microsoft.com/en-us/library/system.componentmodel.designerserializationvisibilityattribute.aspx)?  I've never seen it before, and it appears that you've set it to the default value.
Quote from: msdn
Members that do not have a DesignerSerializationVisibilityAttribute will be treated as though they have a DesignerSerializationVisibilityAttribute with a value of Visible. The values of a property marked as Visible will be serialized, if possible, by a serializer for the type. To specify custom serialization for a particular type or property, use the DesignerSerializerAttribute.

Thanks
Title: Re: How to call a combobox
Post by: TheMaster on May 14, 2013, 03:28:59 PM

What is the purpose of [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )] (http://msdn.microsoft.com/en-us/library/system.componentmodel.designerserializationvisibilityattribute.aspx)?  I've never seen it before, and it appears that you've set it to the default value.
Quote from: msdn
Members that do not have a DesignerSerializationVisibilityAttribute will be treated as though they have a DesignerSerializationVisibilityAttribute with a value of Visible. The values of a property marked as Visible will be serialized, if possible, by a serializer for the type. To specify custom serialization for a particular type or property, use the DesignerSerializerAttribute.

Thanks

If you don't apply it, the default behavior causes the PropertyGrid to expand the control (ComboBox) and show its properties, and will serialize them as part of the LinkedButton control that has the reference to the ComboBox in its LinkedComboBox property. 

You don't want that behavior in this case because the referenced ComboBox's  properties are already being serialized independently because it is on the same form.
Title: Re: How to call a combobox
Post by: WILL HATCH on May 14, 2013, 03:54:12 PM
 :? I figured there was a reason... Another for the list of things to learn.  Thanks