tags:

views:

87

answers:

2

Im adding a list of buttons in code and also subscribing to their mouseleave event. For each button i subcribe to the event with an anonymous function, the problem is that when I run the app they are all subscribed to the last anonymous function. Here is the code, I hope I explained myself.

var modules = ModulesSC.GetAllMoudules();
var imageSet = ModulesSC.GetModuleImageSet();

foreach (var module in modules)
{
    var btn = new Button();
    btn.SetResourceReference(Control.TemplateProperty, "SideMenuButton");
    btn.Content = module.Title;
    btn.MouseEnter += (s, e) => { ShowInfo(module.Description); };
    btn.MouseLeave += (s, e) => { HideInfo(); };
    ModuleButtons.Children.Add(btn);
}

protected void HideInfo()
{
   DescriptionLabel.Visibility = Visibility.Collapsed;
   DescriptionText.Text = string.Empty;
}

protected void ShowInfo(string description)
{
   DescriptionLabel.Visibility = Visibility.Visible;
   DescriptionText.Text = description;
}

When i run the app they all call showInfo with the las "module.Description"

Thanks -Alejandro

A: 

I don't know what language this is, but it could be C#.

If it is, Button click event handlers need to have an "object sender" and an EventArgs argument to the function.

The "object sender" can tell you what button was pressed.

Button pressedButton = (Button)sender;
if(pressedButton.Text.Equals("Button 1")
    doStuff();

That's just an example, there's better ways of determining which button it is than comparing the text field, but you get the idea.

Crowe T. Robot
+3  A: 

This is an issue with the way C# closes over loop variables. Add a temporary variable inside and use that in your anonymous method:

foreach (var module in modules)
{
    var theModule = module;  // local variable
    var btn = new Button();
    btn.SetResourceReference(Control.TemplateProperty, "SideMenuButton");
    btn.Content = theModule.Title;  // *** use local variable
    btn.MouseEnter += (s, e) => { ShowInfo(theModule.Description); };  // *** use local variable
    btn.MouseLeave += (s, e) => { HideInfo(); };
    ModuleButtons.Children.Add(btn);
}

Note the use of the local variable "theModule" instead of the loop variable "module."

itowlson
That work great, thanks
alejandrobog