1
votes

I'm trying to programmatically add a MouseEntered event to a custom NSButton class, and I can't seem to get it to fire. I'm writing a Mac OS application in Visual Studio for Mac, using Xamarin.Mac. I need to add the event in code because I'm creating the buttons dynamically.

Here's my ViewController where these buttons are being created. They're instantiated in the DrawHexMap method near the bottom.

public partial class MapController : NSViewController
{
    public MapController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        DrawHexMap();
    }

    partial void GoToHex(Foundation.NSObject sender)
    {
        string[] coordinateStrings = ((NSButton)sender).Title.Split(',');

        Hex chosenHex = HexRepo.GetHex(coordinateStrings[0], coordinateStrings[1]);
        HexService.currentHex = chosenHex;

        NSTabViewController tp = (NSTabViewController)ParentViewController;
        tp.TabView.SelectAt(1);
    }

    private void DrawHexMap()
    {
        double height = 60;

        for (int x = 0; x < 17; x++) {

            for (int y = 0; y < 13; y++) {
                HexButton button = new HexButton(x, y, height);

                var handle = ObjCRuntime.Selector.GetHandle("GoToHex:");
                button.Action = ObjCRuntime.Selector.FromHandle(handle);
                button.Target = this;

                View.AddSubview(button);
            }
        }

    }
}

And here's the custom button class.

public class HexButton : NSButton
{
    public NSTrackingArea _trackingArea;

    public HexButton(int x, int y, double height)
    {
        double width = height/Math.Sqrt(3);
        double doubleWidth = width * 2;
        double halfHeight = height/2;
        double columnNudge = decimal.Remainder(x, 2) == 0 ? 0 : halfHeight;

        Title = x + "," + y;
        //Bordered = false;
        //ShowsBorderOnlyWhileMouseInside = true;

        SetFrameSize(new CGSize(width, height));
        SetFrameOrigin(new CGPoint(width + (x * doubleWidth), (y * height) + columnNudge));

        _trackingArea = new NSTrackingArea(Frame, NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseEnteredAndExited, this, null);
        AddTrackingArea(_trackingArea);
    }

    public override void MouseEntered(NSEvent theEvent)
    {
        base.MouseEntered(theEvent);

        Console.WriteLine("mouse enter");
    }
}

So as you can see, I'm creating a tracking area for the button and adding it in the constructor. Yet I can't seem to get a MouseEntered to fire. I know the MouseEntered override in this class works, because when I call button.MouseEntered() directly from my code, the method fires.

A few other things I've tried include: Commenting out the lines that set the Action and Target in the ViewController, in case those were overriding the MouseEntered handler somehow. Setting those values inside the HexButton constructor so that the Target was the button instead of the ViewController. Putting the MouseEntered override in the ViewController instead of the button class. Creating the tracking area after the button was added as a subview to the ViewController. None of these made a difference.

Any help would be much appreciated! It's quite difficult to find documentation for Xamarin.Mac...

Thanks!

1
@SushiHangover I didn't, but I just added it, and unfortunately it doesn't make a difference.Nat Webb

1 Answers

1
votes

You are adding the Frame as the region tracked, but you are attaching the tracking area to the view that you are creating the region from, thus you need to track the Bounds coords.

_trackingArea = new NSTrackingArea(Bounds, NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseEnteredAndExited, this, null);

Note: If you were tracking from the view that you are adding the buttons to, then you would need to track the "Frame" as it is the tracking region is relative to the view being tracked, not its children.