I think I've run into a thread synchronization problem. I have a C# program where I have a extended Panel class (MapEditorPanel) and I also have a form that contains that MapEditorPanel. I have a MouseClick Event on both the Form and the Panel. The MapEditorPanels event updates the variables activeRow and activeColumn, which are the column and row that was clicked on.

How can I update the form that contains this MapEditorPanel with the activeRow and activeColumn after the panel is clicked?

When I had originally is two click events. One I set on the Form that is raised when the MapEditorPanel is clicked, but if I try to access the activeColumn and activeRow immidiately after the panel is clicked it loads the previous activeRow and Column because the MapEditorPanel has not finished calculating which row and column were clicked. (Which is called by its MouseClick event).

This is the FORMS MouseClick event:

private void mapViewer_MouseClick(object sender, MouseEventArgs e)
        {
            // Remove red border from old active tile
            if (activeTile != null)
                activeTile.removeTileEffect();

            activeTile = map[mapViewer.ActiveColumn, mapViewer.ActiveRow];

            RowBox.Text = "" + activeTile.Row;
            ColumnBox.Text = "" + activeTile.Column;
            BaseImageBox.Text = "" + activeTile.getBaseImageDescription();
            TopImageBox.Text = "" + activeTile.getTopImageDescription();

            // Add red border to active tile
            activeTile.addTileEffect(gm.getTileEffect("RedBorderTile"));
        }

This is the PANELS MouseClick event:

private void MapEditorPanel_MouseClick(object sender, MouseEventArgs e)
        {

            Point mapCoordinates = getMapPointFromScreen(e.Location);
        
            Tile tileClicked = map.getTileFromPoint(mapCoordinates);

            activeRow = (tileClicked.Row);
            activeColumn = (tileClicked.Column);

        }

Recommended Answers

All 4 Replies

Im not sure that this question has to do with threading at all... it seems you need to create a custom event in your panel that your form subscribes to. that just tells the from that its done calculating, and just move the code from your FORM's click event handler to the custom event handler method on the form that handles the custom event that is fired when the panels mouse click events code is finished. easy huh lol. Im not 100% on how your code works, so the code I am posting is for referenced only. I can't garantee you can just past it in to get the desired effect. but then again. it will probably work fine.

so in the PANEL you would create a custom event like so

//create delegate for event
        public delegate void panelClickerHandler(object myObject,
                                     EventArgs myEvent);
       //expose delegate for subscription
        public event panelClickerHandler OnPanelClicker;

and add a event throw at the end of your click event.

private void MapEditorPanel_MouseClick(object sender, MouseEventArgs e)
        {

            Point mapCoordinates = getMapPointFromScreen(e.Location);
        
            Tile tileClicked = map.getTileFromPoint(mapCoordinates);

            activeRow = (tileClicked.Row);
            activeColumn = (tileClicked.Column);

             //throw event to notifiy subscribed objects that we are 
             //done here

              OnPanelClicker(this, EventArgs.Empty);
        }

ok. so now we need our FORM to be subscribed to that event. and its clicked event should not be used in this case(I think, im not all that sure how your appy works.)

so we subscribe to the event.

//as I am unsure of your panel instance name. 
I will refer to it as [I]yourpanel[/I]

//subscribe to event and create a handler

[I]yourpanel[/I].OnPanelClicker += new panelClickerHandler(panelClickdone);

//now the method that replaces what would have been your form clicked handler

private void panelClickdone(object sender, EventArgs e)
{
   // Remove red border from old active tile
            if (activeTile != null)
                activeTile.removeTileEffect();

            activeTile = map[mapViewer.ActiveColumn, mapViewer.ActiveRow];

            RowBox.Text = "" + activeTile.Row;
            ColumnBox.Text = "" + activeTile.Column;
            BaseImageBox.Text = "" + activeTile.getBaseImageDescription();
            TopImageBox.Text = "" + activeTile.getTopImageDescription();

            // Add red border to active tile
            activeTile.addTileEffect(gm.getTileEffect("RedBorderTile"));

}

and that's it. it should wait til the panel has handled its click, then call the method on the form.

Happy Coding.

Thanks for the help. I've never made a custom event handler before. That's probably why I never thought to do that. It's a good time to learn I guess.

Thanks again,

Nick

DiamondDrake, is it possible to call the form click handler from inside the panel click handler or is your VERY instructive example(thanks) the "best" way to do this?

It is possible just to create a public method in the form and call it from the panel. though it makes the panel easier to reuse in other forms when you use an event. i'm not sure exactly how he was passing his data between the form and the panel, but another benefit to using an event is you can create a custom event args class, and pass any information you need to your event handler. This would prevent you from needing to create a large amount of properties to send information back to the form.

but in this case, either one would seem to work equally well.

commented: Think your solution is better : custom event args... +6
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.