Most validation belongs in the FORM's BeforeUpdate event. That way it is executed no matter what causes a record to be saved. In some cases, you can use the control's BeforeUpdate event but that generally results in validation code being in two events because you can't for example verify "presence" in the control's BeforeUpdate event since control level events do not fire unless a control actually gets the focus.
A better solution would be:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsDate(Me.[Dateclosed]) And Me.[Status] <> "Closed" Then
Me.[Status] = "closed"
MsgBox "Date closed and status conflict.",vbOKOnly
Cancel = True
However, As I mentioned earlier, this is not a good design.
If all you want is the most recent status, then you can use one Status field and one StatusDate field. However, if you want to track ALL status changes, then you must create a separate status table where you can insert one row for each previous status.
I keep the current status in the main table. When the status changes, I write the previous status to the status table and change the current status. Others, might always store all status' in the status table. That design choice complicates queries and processing and frequently results in queries that you need to be updateable not being updateable because you have to use a subquery with Max() to obtain the current status.