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:
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.
One thought on “The strange case of ProjectItem.Open(EnvDTE.Constants.vsext_vk_Designer) trying to check-out a form file”
In reading your solution it was able to point me into the root cause of this problem. If any control has an automatic size change event this issue will be triggered. For example, the IDE creates labels with Autosize to true, docking the label will cause this, docking a list box without setting integral height will cause this, and as you have seen, events created before the discovery of docking.
Comments are closed.