How to call a method from programmatically created buttons with different parameters?

115 views Asked by At

my problem is how to call a existing method from another object with button specific parameters. This is the method I need to call ( from MainWindow):

partial class Sidebar : Window
{
    [...]
    internal void SetPosition(System.Drawing.Rectangle workingarea, bool left)
    {
      Overlay.Properties.Settings.Default.SidebarSide = left;
      Overlay.Properties.Settings.Default.Top = this.Top = workspace.Top;
      Overlay.Properties.Settings.Default.Left = this.Left = workspace.Left;
      Overlay.Properties.Settings.Default.Save();
      this.Height = workspace.Height;
      this.Width = workspace.Width;
      timeGrid.Style = gridStyle;
      Refresh();
    }
    [...]
}

and following is the method for creating buttons (and more) for each Screen connected to the machine

class SettingsWindow : Window
{
    [...]
    private void SidebarTab_Initialized(object sender, EventArgs e)
            {
                Canvas monitorCanvas = new Canvas();
                spPosition.Children.Add(monitorCanvas);

            System.Windows.Forms.Screen currentScreen = System.Windows.Forms.Screen.FromHandle(
                new System.Windows.Interop.WindowInteropHelper(this).Handle);
            System.Windows.Forms.Screen[] screens = System.Windows.Forms.Screen.AllScreens;

            Point min = new Point(0,0);
            Point max = new Point(0,0);

            for (int i = 0; i < screens.Length; i++)
            {
                min.X = min.X < screens[i].Bounds.X ? min.X : screens[i].Bounds.X;
                min.Y = min.Y < screens[i].Bounds.Y ? min.Y : screens[i].Bounds.Y;

                max.X = max.X > (screens[i].Bounds.X + screens[i].Bounds.Width) ? max.X : (screens[i].Bounds.X + screens[i].Bounds.Width);
                max.Y = max.Y > (screens[i].Bounds.Y + screens[i].Bounds.Height) ? max.Y : (screens[i].Bounds.Y + screens[i].Bounds.Height);
            }
            [...]


            for (int i = 0; i < screens.Length; i++)
            {

                Border monitor = new Border();
                monitor.BorderBrush = Brushes.Black;
                monitor.BorderThickness = new Thickness(1);
                Canvas.SetTop(monitor, (screens[i].Bounds.Top - min.Y) / scale);
                Canvas.SetLeft(monitor, (screens[i].Bounds.Left - min.X) / scale);
                monitor.Width = screens[i].Bounds.Width / scale;
                monitor.Height = screens[i].Bounds.Height / scale;

                DockPanel dp = new DockPanel();

                Button monLeft = new Button();
                monLeft.Width = scale;
                DockPanel.SetDock(monLeft, Dock.Left);

                Button monRight = new Button();
                monRight.Width = scale;
                DockPanel.SetDock(monRight, Dock.Right);
                [...]
                }
            }

}

As you see, I need two buttons for every screen on the machine.
monLeft.Click = SetPosition(screens[i].WorkingArea, true); and
monRight.Click = SetPosition(screens[i].WorkingArea, true); is what I need.

Thanks in advance.

2

There are 2 answers

1
Servy On BEST ANSWER

Use a lambda to define the event handler. This allows you to close over the local variable(s) that you'll need in your handler.

Note that closures close over variables, not values, so you don't want to close over i (it won't be the value that you want it to be by the time the event fires). You'll need to make a copy of the loop variable inside of the loop so that you can close over that instead. Well, that or use a foreach loop (in C# 5.0+) instead of a for loop.

foreach(var screen in screens)
{
    //...

    Button monRight = new Button();
    monRight.Width = scale;
    DockPanel.SetDock(monRight, Dock.Right);
    monRight.Click += (s,e) => SetPosition(screen.WorkingArea, true);
}
2
Rafael Costa On

Well, as you can see in http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.click(v=vs.110).aspx, Button.Click is an event, so you need to assign an event handler to it:

Either you wrap your SetPosition() method in an event handler and assign the event handler of your Button.Click event to it, or you can do it through lambda construction as suggested in the previous answer.

Another alternative is setting the Button.Command for your buttons, by implementing an instance of ICommand that will call the SetPosition() method.