The pattern itself doesn't really prescribe how to handle this.
My own preference is a message/event hub where presenters can register interest in certain events. It prevents complex dependency trees and keeps the presenters testable.
For example:
class PresenterA
{
void HandleProductSelectionChanged(int productId)
{
EventHub.Publish(EventType.ProductChanged, productId);
}
}
class PresenterB
{
void PresenterB
{
EventHub.Register(EventType.ProductChanged, HandleProductChanged);
}
public void HandleProductChanged(object state)
{
var productId = (int)state;
var productDetails = LoadProductDetails(productId);
view.DisplayProductDetails(productDetails);
}
}
EventHub would keep a list of subscribers to invoke for each event type.
You retain your testability - simply call on HandleProductChanged
to see how PresenterB would respond to a new product selection.
The only disadvantage (as with any pattern) is you introduce a level of indirection. If PresenterA directly invoked PresenterB, or PresenterB listened to an event on PresenterA, it is immediately obvious what's going to happen.
In this approach, you would have the extra step seeing EventType.ProductChanged, and then finding which Presenters registered an interest in that event.
In my own experience, that single level of indirection is well worth modularity you get.