In a WPF application, suppose there are 'n'-number of pictures of type image and if on clicking any picture (i.e. of type image), its visibility should collapse. Now a normal way to do this would be to to write the code to collapse for every 'Click' event for every picture.
Is there an alternative way so that the application can understand that whenever any UIelement(picture) of type image is clicked then that particular element(picture) should collapse?
I want to reduce the code, how can I achieve this?
Asked
Active
Viewed 1,903 times
3

Dave Clemmer
- 3,741
- 12
- 49
- 72

Siddharth Thevaril
- 3,722
- 3
- 35
- 71
3 Answers
3
You can take advantage of the fact that these are Routed Events, and set a single handler on a parent element.
This allows a single event handler to handle all events of the child controls. The OriginalSource
property of the event args will provide the UIElement that was clicked, if, for example, you subscribed to UIElement.MouseLeftButtonDown
or a similar "shared" event.
You would do this by adding, in your XAML, to your container:
<Grid UIElement.MouseLeftButtonDown="CommonClickHandler">
<!-- Your elements here -->
Then, in your code behind:
private void CommonClickHandler(object sender, MouseButtonEventArgs e)
{
Image picture = e.OriginalSource as Image; //OriginalSource is the original element
if (picture != null)
picture.Visibility = Visibility.Collapsed;
}

Reed Copsey
- 554,122
- 78
- 1,158
- 1,373
-
I'm still getting my hands on C#, can you please give a short code example? – Siddharth Thevaril Aug 02 '13 at 19:50
-
This solution works the closest to what I wanted! Why did you choose MouseButtonEventArgs over RoutedEventArgs? What benefit does it have? – Siddharth Thevaril Aug 03 '13 at 19:50
-
1@Sidsec9 In this case, no benefits. However, the MouseLeftButtonDown event is declared that way, so it can pass through the extra info. Since that specific event uses MouseButtonEventArgs, my method does as well. (MouseButtonEventArgs derives from RoutedEventArgs, but provides extra info) – Reed Copsey Aug 03 '13 at 19:56
-
C# now has new syntax that simplifies this... `if(e.OriginalSource is Image picture) { ... }` Using that syntax, you don't have to explicitly define `picture`, and it now only exists in the scope of the `if` clause where it's also guaranteed to not be null. – Mark A. Donohoe Sep 05 '22 at 16:31
2
You can add global handler using EventManager.RegisterClassHandler like this -
public MainWindow()
{
InitializeComponent();
EventManager.RegisterClassHandler(typeof(Image), Image.MouseDownEvent,
new RoutedEventHandler(OnMouseDown));
}
private void OnMouseDown(object sender, RoutedEventArgs e)
{
(sender as Image).Visibility = System.Windows.Visibility.Collapsed;
}

Rohit Vats
- 79,502
- 12
- 161
- 185
-
This works perfectly! I have a question though, what should I do if I want one picture to function differently from the rest? – Siddharth Thevaril Aug 03 '13 at 19:18
-
You have `sender` in your handler. You can check on image name or some other property in there and do your work for the image that needs to be handled specially. – Rohit Vats Aug 03 '13 at 19:26
1
You can register the method you are using on multiple event handlers and get access to the particular control by using Object sender
parameter and casting it to the type of control you are using.
myControl.Click += new EventHandler(myGenericClickMethod);
public void myGenericClickMethod(Object sender, EventArgs e)
{
Image myImage = (Image) sender;
myImage..Visibility = System.Windows.Visibility.Collapsed;
}

Cam Bruce
- 5,632
- 19
- 34
-
-
I believe this can be simplified even further to just `myControl.Click += myGenericClickMethod;` No need to manually 'new up' an event handler. – Mark A. Donohoe Sep 05 '22 at 16:32