When you design and develop an application, we very often use the controls that the platform offers. For example, let’s say we are developing a WinForm for the client side, Microsoft offers us many controls and many attributes and events that we can customize for those controls. Attributes change appearance, eg background color, text etc. and events enrich the control, most commonly button click. No one knows what will happen after the button is clicked, it’s a generic name. So providing an Onclick event to the developer is the best solution.

SubView Behavior Change

After discussing why we should use “reusable”, we realized that these components can be used in any scenario. But how can we be sure that it will do the right thing in every scenario? For example, let’s consider that the icon we designed before should behave differently for different situations…

In Game Char Icon

  • Click to show a user’s information on a battlefield.
  • Clicking the icon of a user in a team to see the subprocesses.
  • Click to see your tactics during the battle.

As you can see, a SubView can have many different behaviors.

Customizing SubView Behavior

Maybe “Middle Eastern Ferhat S.” You may want to implement what is known as a principle, as seen below:

void OnClick(){
	if(InBattleMode){
		ShowMemberInfo();
	}else if(InTeamMode){
		ShowAllOptions();
	}else if(InWar){
		ShowMemberTactics();
	}else{
		//PlayClick();
	}
}

This implementation may seem very suitable for some SubViews, but it is not true.

  • Adding else if to add new behaviors is against the Opening and Closing principles of SOLID principles.
  • As long as the SubView is reusable, we should be able to put it on every object, but this implementation does it for a specific game/app.
    We clearly see that this implementation is not suitable. What should the solution be?
    It will be our approximate solution in the example we gave earlier. It doesn’t matter if it’s a button or an icon, if it’s “reusable”, it should allow customization with the delegate given to an event.

Adding a Delegate

In line with the analysis we did earlier, should the delegate or event be in a SubView or in a SubViewModel? If we reiterate that the View does nothing special and just forwards requests to the ViewModel, we would have answered that.

We add the required delegates to the FaceBoxViewModel for this example.

public class FaceBoxViewModel:ViewModelBase
{
	//...  
	public delegate void OnBeginDragHandler();
    public OnBeginDragHandler OnBeginDrag;
    public delegate void OnDragHandler();
    public OnDragHandler OnDrag;
    public delegate void OnEndDragHandler();
    public OnEndDragHandler OnEndDrag;
    public delegate void OnClickHandler();
    public OnClickHandler OnClick;
	//...
}

Let’s implement it so that FaceBoxView does a custom job and those jobs are handled by the FaceBoxViewModel:

protected override void OnInitialize()
{
    //...
    var beginDragEntry = new EventTrigger.Entry();
    beginDragEntry.eventID = EventTriggerType.BeginDrag;
    beginDragEntry.callback.AddListener(eventData => { OnBeginDrag(); });
    eventTrigger.triggers.Add(beginDragEntry);

    var dragEntry = new EventTrigger.Entry();
    dragEntry.eventID = EventTriggerType.Drag;
    dragEntry.callback.AddListener(eventData => { OnDrag(); });
    eventTrigger.triggers.Add(dragEntry);

    var endDragEntry = new EventTrigger.Entry();
    endDragEntry.eventID = EventTriggerType.EndDrag;
    endDragEntry.callback.AddListener(eventData => { OnEndDrag(); });
    eventTrigger.triggers.Add(endDragEntry);

    var pointClickEntry = new EventTrigger.Entry();
    pointClickEntry.eventID = EventTriggerType.PointerClick;
    pointClickEntry.callback.AddListener(eventData => { OnClick(); });
    eventTrigger.triggers.Add(pointClickEntry);
}

private void OnClick()
{
    if (BindingContext.OnClick != null)
    {
        BindingContext.OnClick();
    }
}

If we visualize it in our minds, the flow goes like this. FaceBoxView.PointClick -> FaceBoxViewModel.OnClick() -> Dedicated custom job.