Click here to Skip to main content
15,881,559 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi all!

Here is tricky question. I have listbox which hold X quantity of my dataclasses. I represents my dataclasses trough listbox itemtemplate which contains textblocks, picture and button. listBox_SelectionChanged event (starts when you just click some listbox item) starts process which uses listbox selected item dataclass as parameter. Works just fine!

But here it comes the tricky question, like I said I have button in my listbox itemtemplate so every listbox item has button which should start different task with that item which button was pressed as parameter. How do I do that? Normally with button click events I just chooce listboxitem and then I press its button but now I cant press listbox item because it will fire different task than my button event.

Kinda weird situation, but I hope you got idea :)

Cheers!
Posted

There is nothing weird in this situation. To tell you more, there are many very similar questions here at CodeProject; this topic is actually one of the popular ones. No wonder, this situation is very natural.

Now, there can be different solutions, but there is nothing tricky at all.
Here is one of the ways which I think is robust enough. Another good thing: it can be used with both WPF and System.Windows.Forms.

(You need to uniquely identify the button. Many advise to use the name or even button text. Please, never do that! It is not a supportable way.)

Instead of attempting to identify a button, put some information in its tag. It should be some information we use at the moment of click, and can be anything: enumeration (what kind of action to take), a structure or a class (data used at the moment of click, such as database key or what ever):

C#
internal class ButtonClickInfo {
    internal ButtonClickInfo(/*...*/) { /*...*/ }
    //...
}


Now, for every button, add an appropriate instance of this type and appropriate handler:

C#
Button btn;

//...

btn.Tag = new ButtonClickInfo(//... different parameters for each button
btn.Click += (sender, eventArgs) => {
    Button thisButton = (Button)sender; //not need in "as": you defined it as a button 2 lines above
    ButtonClickInfo info = (ButtonClickInfo)(thisButton.Tag); //same thing, cast with no worries
    PerformButtonClickActionDependingOnButtonClickInfo(info); //whatever you want, one method for all buttons
};


You can automate this procedure of setting Tags and Click event handlers: parametrize the data passed to tag (this should be the only difference between buttons) and run it in some loop, depending on item data, etc.

Now, pay attention: thanks to the anonymous delegate, you do not have to pass any of the unused parameters like sender and eventArgs to the handler method; you already extracted ButtonClickInfo instance from the Button instance, and this is all what matters. You pass only essential data to PerformButtonClickActionDependingOnButtonClickInfo. Therefore, I don't recomment using any event handlers auto-generated by the Designed: it will generate obsolete-style code which is hard to support. Doing it by coding the way I illustrated above is much faster and better for supportability.

—SA
 
Share this answer
 
v6
Comments
paleGegg0 31-Mar-11 0:06am    
Wow! thanks for the answer! I truly appreciate that you not only give the answer but also codesnippet and pointing out benefits of this solution. Its shame that cannot give more than 5 points. Have a good day :)!
Sergey Alexandrovich Kryukov 31-Mar-11 0:09am    
Sure.
Thanks for accepting this answer.
Good luck, call again.
--SA
Hi,

if I understand correctly. You have many items in your listbox and in every item is a button. And you want to get the object on which you have clicked the Button.

I would propose two options:

First you could get the DataContext from the sender and cast it to your Object.
MyClass my = (sender as Button).DataContext as MyClass; 


Second your could use RelayCommand. Look at these Articles:
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030[^]
http://stackoverflow.com/questions/862570/relaycommand-in-wpf[^]


Hope it helps
 
Share this answer
 
Comments
paleGegg0 31-Mar-11 0:01am    
thanks for your answer, works also like above answer :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900