• 0

[C#] Dynamic Event Handling


Question

I have an arbitrary list of elements that I'm adding to a tableLayoutPanel (it was the first layout I came across that I could add elements to and it would be scrollable). For each element, I add the name of the element, with a TrackBar and a TextBox. (so three controls per row).

I want to link the TrackBar with the TextBox in a way where when I move the TrackBar, it changes the numeric value in the textBox to the value of the TrackBar (and ViceVersa).

I know how to add the Events for the two (+= new EventHandler(Scrolled)). The problem is all my elements are being added with the same EventName, so no matter which control I manipulate, i want the corresponding controls to change as well... I think this is OK, because I don't know how many of these elements I will have until runtime.

My question is this... inside the Scrolled method, how can I make elementScrollBar1 change elementTextBox1, and 2 -> 2, 3 -> 3, etc? The only things passed in are object sender, EventArgs events. Is what I'm trying to do possible? If so please help.

Link to comment
https://www.neowin.net/forum/topic/610910-c-dynamic-event-handling/
Share on other sites

21 answers to this question

Recommended Posts

  • 0

You need something like this:

		private void AddControls_Click(object sender, EventArgs e)
		{
			TextBox textbox = new TextBox();
			TrackBar trackbar = new TrackBar();
			trackbar.Maximum = 10;
			trackbar.Tag = textbox;

			trackbar.Scroll +=  delegate(object sender2, EventArgs e2)
								{
									TrackBar currentTrackBar = sender2 as TrackBar;
									TextBox currentTextBox = currentTrackBar.Tag as TextBox;
									currentTextBox.Text = currentTrackBar.Value.ToString();
								};
			tableLayoutPanel1.Controls.AddRange(new Control[] { textbox, trackbar });

		}

Add that into a button click event.

Hope this helps.

  • 0

My controls are added dynamically when the program is run, not by a click event... I'm guessing replacing my code with this for those two controls will have the same effect? Looking at this it seems like I should do this for other trackbar/textbox combos I have... this links the two I'm guessing?

Does this also allow someone to edit the textbox and it affect the trackbar?

  • 0

I figured out that it doesn't and modified my code to make it work.. I did something similar to what you showed, using the textBox.Tag = trackBar to put a reference.

Is this common practice? If I want to relate two controls, should I just reference each within the Tag variable? Is that common practice? It seems a little odd to me, even though it works as a hack.

  • 0

Why don't you create a custom control that includes the elements you need, and put the logic there? That's probably the most common practice in this case, since it's exactly why custom controls exist...

Just add a new UserControl to your project, name it something useful, and add a TextBox and Trackbar to it with the layout you want. Then set up the event handlers as you normally would inside the control, you can even use the Forms Designer for all of this.

Then in your main app, instead of dynamically generating TextBoxes and Trackbars, you add MyCustomControls that encapsulate the functionality you need. If you need to you can then expose a method or property on your custom control like GetValue() that returns the value (as indicated by both the textbox and trackbar).

  • 0

I didn't know about this custom control stuff, this seems to be much easier to work with... but I have a new problem because of it

So I have a control with a bunch of controls, one of them again linking a trackbar to a textBox... when I manipulate the trackBar, it updates the textBox correctly.. I have all the event stuff inside the Control Class... but the problem is, whenever I change the trackBar I want to call my update() method from the main class (Form1)... How would one do this?

Edited by zackiv31
  • 0
  zackiv31 said:
I didn't know about this custom control stuff, this seems to be much easier to work with... but I have a new problem because of it

So I have a control with a bunch of controls, one of them again linking a trackbar to a textBox... when I manipulate the trackBar, it updates the textBox correctly.. I have all the event stuff inside the Control Class... but the problem is, whenever I change the trackBar I want to call my update() method from the main class (Form1)... How would one do this?

Ideally, your control would expose an event that would notify any listeners that the trackbar has changed.

  • 0

You would create a delegate and an event that are public in your user control, and when you handle the trackbar change event in your user control, you fire another event indicating that it changed to the 'outside' world.

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

namespace cs3
{
	public delegate void ValueChangedHandler(object sender, int newValue);

	public partial class UserControl1 : UserControl
	{
		public UserControl1()
		{
			InitializeComponent();
			textBox1.Text = trackBar1.Value.ToString();
		}

		[Category("Action")]
		public event ValueChangedHandler ValueChanged;

		private void trackBar1_ValueChanged(object sender, EventArgs e)
		{
			textBox1.Text = trackBar1.Value.ToString();
			OnValueChanged(trackBar1.Value);
		}

		protected void OnValueChanged(int newValue)
		{
			if (ValueChanged != null)
				ValueChanged(this, newValue);
		}
	}
}

  • 0
  zackiv31 said:
		[Category("Action")]
		  public event ValueChangedHandler ValueChanged;

This is new to me.. but seems interesting... what exactly are the [] for? What does it represent or tell he compiler?

It's an attribute for the designer. Add the control to your form, and then select the control. In the Properties pane of the designer, you see properties categorized. If you click on the Events button(the lightning bolt), it lists the events that your control exposes. If you didn't put the CategoryAttribute above your event, it would show up at the bottom of the list in the Misc category.

Attributes are one of the cool aspects of .NET that can be leveraged in many interesting ways. You could effectively describe your class with attributes and discover the metadata at runtime, and perform actions based on it. I've built a framework that utilized attributes to describe how properties should be validated. It was only a proof of concept, but it worked quite well. I'm now seeing that same idea show up in other frameworks, such as the Castle Project's MVC framework.

Edited by azcodemonkey
  • 0

here's my userControl:

	public delegate void ValueChangedHandler(object sender);

	public partial class ListBag : UserControl
	{
		[Category("Action")]
		public event ValueChangedHandler ValueChanged;

here's the declaration in Form1:

ListBag lb = new ListBag();
					lb.ValueChanged += new ValueChangedHandler;

It doesn't recognize this, it tries to make it " += ValueChangedHandler(someNameHere)"...

  • 0

But you said you wanted your Form1 to know when something changed inside the user control. That's why you need to have a method inside Form1 that gets called when the event is fired. It can be named anything you want (like OnListBagValueChanged or something).

  • 0
  zackiv31 said:
wo wo wo... OnValueChanged is a part of my custom UserControl... therefore Form1 has no idea abou the inner workings of it...

someone confirm this? (and help still)

Your form needs to have a method that matches the signature of the delegate of your control.

protected void UserCtrlValueChanged(object sender)
{
	...
}

Then you can use the += syntax to add a new handler in your form's InitializeComponent method.

userCtrlInstance.ValueChanged += new ValueChangedHandler(UserCtrlValueChanged);

You should be able to do this completely through the designer. Add the control to your form, select the control, go to the Properties panel in the IDE and select the Event(lightning bolt), and double-click the ValueChanged event in the UI. This will do all of the above correctly for you.

Edit: Brandon got it. :)

  • 0

Not that it matters much, but if that's what you delegate looks like - you don't actually need a custom one. Just use the built-in EventHandler delegate. Other than that little nit, it looks like you've got things figured out.

  • 0

Well it depends. Are you using:

public delegate void ValueChangedHandler(object sender);

or

public delegate void ValueChangedHandler(object sender, int newValue);

If the latter, then just keep it as is. If the former, then you don't need to declare that delegate at all.

protected void UserCtrlValueChanged(object sender)
{
...
}

in your main form, becomes

protected void UserCtrlValueChanged(object sender, EventArgs e)
{
...
}

And everywhere you used "ValueChangedHandler" before, you could now use just the built-in EventHandler delegate.

For example:

userCtrlInstance.ValueChanged += new ValueChangedHandler(UserCtrlValueChanged);

becomes

userCtrlInstance.ValueChanged += new EventHandler(UserCtrlValueChanged);

But if you are using a custom delegate to pass an integer with the new value, then you'll want to keep doing it the way you are. And when the event is raised, you just pass EventArgs.Empty for the second parameter.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • I'm just thinking out loud for a second...could it be the cookie prompt that kicks up the adblock message? The reason I ask is that on Firefox (ad-block enabled but not for Neowin) I don't get the cookie consent option. But if I open Chrome (ad-block disabled) and go to the Neowin I get the cookie banner and then it's all fine. Some form of conflict of interest between the banners? It's probably nothing, but that's what I have just noticed.
    • SoundSwitch 6.14.1 by Razvan Serea SoundSwitch is a Windows app that makes switching your sound devices super easy. Normally, changing speakers or microphones means clicking through annoying menus. With SoundSwitch, you just press a shortcut key (like Ctrl + Alt + F1) — and it switches to the device you want. You can set different keys for speakers, headphones, microphones, or even groups of devices. It also lets you mute your mic with a hotkey and shows a clear banner so you know it's muted. It runs in the background, shows up in your taskbar, and starts with Windows if you want. It’s perfect if you use multiple audio devices and get tired of clicking around every time you want to change one. SoundSwitch features: Customizable Hotkeys: Assign specific key combinations to switch between audio devices quickly. ​ Playback and Recording Device Switching: Toggle between selected playback and recording devices without navigating through system menus. ​ Microphone Mute Toggle: Use hotkeys to mute or unmute the default microphone. ​ Persistent Mute Notification: Displays a compact banner indicating the microphone's mute state, which remains visible until the microphone is unmuted. ​ Profile Management: Create profiles to switch between specific combinations of playback and recording devices using designated hotkeys. ​ Command Line Interface (CLI): Control SoundSwitch through command-line commands for device switching, microphone mute control, and profile management. ​ Auto-Start with Windows: Option to launch SoundSwitch automatically upon system startup. ​ Multi-Language Support: Includes translations for various languages, such as Tamil. ​ Notification Customization: Choose the type of notifications displayed for device switching and mute status. ​ Support for Various Hotkey Combinations: Accepts single keys like PrintScreen, Pause, Home, End, and function keys as hotkeys. ​ System Tray Integration: Access settings and perform device switching directly from the system tray icon. ​ Device Grouping: Organize multiple devices into groups for streamlined switching. ​ User-Friendly Interface: Provides an intuitive setup and configuration process for users. ​ Open-Source Development: Available on GitHub for community contributions and transparency. ​ Regular Updates: Actively maintained with new features and bug fixes. ​ SoundSwitch 6.14.1 changelog: Bug Fixes settings: fix opening settings crashing the application when using CLI or opening SoundSwitch again (b3dca74) Languages Amharic: Added About translation using Weblate (8a40dab) Japanese: Translated About using Weblate (3541994) Japanese: Translated Settings using Weblate (ca5b2fe) Japanese: Translated Settings using Weblate (39a2340) Japanese: Translated Tray Icon using Weblate (1286b92) Japanese: Translated Update Download using Weblate (1c2c658) Norwegian Bokmål: Translated Settings using Weblate (5aaf243) Portuguese: Translated Settings using Weblate (e11f18d) Swedish: Translated Settings using Weblate (8b7b738) Download: SoundSwitch 6.14.1 | 45.4 MB (Open Source) View: SoundSwitch Website | Github | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Wow, the usual crowd is out in full force again — the trolls who think sarcasm is insight, the doom prophets who scream 'web apps = surveillance', and the armchair devs who still think Outlook 2003 was peak tech. Here’s a wild idea: maybe evaluate an app on what it does instead of what your paranoia imagines it’s doing. The new Outlook is fast, clean, and tightly integrated. No, it’s not perfect — what app is? But if your main tech critique is 'It’s different and Microsoft is evil', you’re not reviewing software. You’re just rehearsing your trust issues. Don't like it? Cool. But at least bring something to the table besides tired one-liners and Chicken Little routines. Some of us actually use this stuff and prefer practical feedback over pointless whining.
    • And they will only last thousands of years underground we don’t know where.
    • Went on a bit of a Bethesda binge recently after the Oblivion remaster release, although not in a positive way. I liked the OG Oblivion and completed it nearly 20 years ago, but the remaster didn't resonate with me in the same way - just feels like it hasn't aged well, gameplay-wise - so I moved onto finally giving Skyrim a go after owning it for so many years, and I had what I've been informed was a classic introduction to the game... It got stuck shortly after that at the point where an NPC's supposed to be thrown on the chopping block and beheaded; everyone just stood in place twiddling their thumbs and not saying their lines (this was the Xbox version too of the 'Special Edition' with no mods enabled). Did the same every time I reloaded, so took it as a sign that even the game was telling me to just bin it, so I did and moved onto Fallout 4, which is alright so far (touch wood).
  • Recent Achievements

    • Reacting Well
      James courage Tabla earned a badge
      Reacting Well
    • Apprentice
      DarkShrunken went up a rank
      Apprentice
    • Dedicated
      CHUNWEI earned a badge
      Dedicated
    • Collaborator
      DarkShrunken earned a badge
      Collaborator
    • Rookie
      Pat-Garrett went up a rank
      Rookie
  • Popular Contributors

    1. 1
      +primortal
      341
    2. 2
      snowy owl
      167
    3. 3
      ATLien_0
      161
    4. 4
      +FloatingFatMan
      161
    5. 5
      Xenon
      128
  • Tell a friend

    Love Neowin? Tell a friend!