The strange case of ProjectItem.Open(EnvDTE.Constants.vsext_vk_Designer) trying to check-out a form file

Today I have solved a problem that was bugging me for months. I was aware of it but I hadn’t paid much attention to it (because I knew it was not a problem of my MZ-Tools add-in) until today, when I decided to take a closer look. The problem was the following: whenever I executed one of the features of MZ-Tools that reviews the designers of forms (such as the TabIndex review, the Access Keys review, etc.), of a solution under source control, the MDI form of the application became checked-out after the review and I had to undo the check-out by hand.

The line of code that caused the check-out was, of course:

ProjectItem.Open(EnvDTE.Constants.vsext_vk_Designer)

and I knew that the problem was not MZ-Tools because opening the designer by hand in the IDE resulted also in a silent check-out. I noticed too that if I disconnected the solution from source control, in this case Visual Studio prompted to edit the read-only file with a dialog with buttons “Edit In-memory”, “Make Writeable” and “Cancel”. So, Visual Studio was really feeling the need of edit a designer file when opening it. But what was causing it?

I have spent the whole morning prunning the project, the form and the code, with several oops-too-much-pruning-that-no-longer-reproduces-the-problem and finally I have a minimal reproducible pattern:

1) Create a new Windows Forms project with Form1.

2) Create a user control UserControl1 with this code:

Private Sub UserControl1_VisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.VisibleChanged

   Me.Size = New Size(100, 100)

End Sub

3) Build the project so the usercontrol appears on the toolbox.

4) Add the usercontrol to the form and set its Dock property to Fill.

5) Build the project again

6) Close all windows

7) Close the solution

8) Using the Windows Explorer, set the read-only attribute of the Form1*.* files

9) Open the solution again

10) Try to open the Form1.vb file in Design view. You get a prompt to edit the read-only file.

I know it’s stupid to set the size of the usercontrol in the VisibleChanged event of a usercontrol that will be docked, but that was what the code was doing in the end …

So, the solutions are:

1) Stop doing stupid things or…

2) Change the code to the following, so it only executes at run-time:

Private Sub UserControl1_VisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.VisibleChanged

   If Not Me.Site.DesignMode Then

      Me.Size = New Size(100, 100)

   End If

End Sub

Is there anything that an add-in can do when it encounters this situation? If VS shows a prompt, there is nothing that an add-in can do. But if VS does a silent check-out, or silently changes the read-only flag of files you can do something: get the read-only value before calling ProjectItem.Open(EnvDTE.Constants.vsext_vk_Designer), get it afterwards, compare them and it they are not the same you can inform the user that there is something wrong in the file or in the controls used in the file, and that the same problem would happen if he opens the designer by hand, so it’s not really add-in’s fault.

Update (March 11, 2009):

If the file is not read-only, then VS edits it behind the scenes and you get an unexpected prompt to save the changes when closing the solution.

Also, I have found other pattern that reproduces the problem without wrong code:

1) Create a Windows Form project in VS 2008

2) Add a ListBox control to Form1 and set its Dock property to Fill

3) Save the changes, close the windows, and close VS

4) Using Windows Explorer, set the read-only attributes of the three Form1*.* files

5) Open VS and load the solution

6) Try to open the Form1.vb file in Design view. You get a prompt to edit the read-only file.