Trouble finding source of a designer exception in VS2010 - winforms

When loading the mainform of a WinForms app I'm working on, I encountered a familiar exception: a "To prevent possible data loss before loading the designer, the following errors must be resolved" error. The stacktrace is as follows:
Object reference not set to an instance of an object.
Instances of this error (4)
1. Hide Call Stack
at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkPropertyDescriptor.SetValue(Object component, Object value)
at System.Windows.Forms.Design.ControlDesigner.CanResetSizePropertyDescriptor.SetValue(Object component, Object value)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializePropertyAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement, CodePropertyReferenceExpression propertyReferenceEx, Boolean reportError)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement)
I know what's causing this error -- there are four lines buried somewhere in the MainForm that make reference to an image object that doesn't exist at design time. I even have an idea of how to fix the error, thanks to this post at MSDN. The trouble is, I can't find the lines from which the exception is thrown. Normally I would navigate to the exception using the Error List window, but it says that there are zero errors. Any ideas as to how I can locate the offending lines?

I usually find that this relates to a user control hosted on the form that relies on a DI container or similar, but as you say it is sometimes difficult to determine the source from the call stack the designer provides. If you're hosting a lot of controls, to figure out which controls are causing the issue without diving into each one you could:
Make a list of the user controls that are directly hosted on the form, then
Create a new temporary form, then
Drop each user control in your list onto the form to see which one kills the designer

Related

Test Runner can't find controls during replay

I just started with Microsoft Test Manager 2015 and build two test cases.
First one involves clicking on a tray icon and selecting an entry from there - which works fine.
Second case is a bit more complex, I wanted to fill out a form in a WPF window and click some buttons.
The recording went without a problem but the replay doesn't work at all. It should start with selecting a TabItem, select another TabItem that is inside the previous selected TabItem and then fill out the text fields and press a button and confirm two message dialogues.
Problem is, TestRunner isn't able to find any of my controls. Even if I select the correct TabItem and just try and execute one of the 'enter someText here' steps, it takes some time and then throws an exception in my face which, roughly translated, says that the replay of the selected step couldn't be completed because it couldn't find a control that matched the search properties(?). Then follows a List:
TechnologyName: 'UIA'
FrameworkId: 'WPF'
ControlType: 'TabPage'
AutomationId: 'sometabname'
all of that is correct. If I try to execute a different test step it says basically the same thing but instead of 'ControlType: TabPage' it says 'ControlType: Edit'.
I'm not sure how to proceed from here. I did some searching but all I could find were questions about UIAutomation configuration/set-up but as far as I can tell I can't influence/control that directly in MTM.
edit
After simplifying the test 'case' (just click the abort button that is directly placed in the Window/first grid) and editing the mtm.exe.config file and enabling tracing/logging I got this out of the respective logfile:
mtm.exe, Playback - [WARNING] Internal warning: Target element "[UIA]FrameworkId='WPF' && ControlType='Button' && AutomationId='closeWithoutSave'" was not found, so all intermediate elements were ignored. An incorrect element that matches target element Id can be found as the result. Verify that all intermediate elements in QueryId have valid and unique Ids
mtm.exe, Playback - [WARNING] Internal warning: Search failure: [UIA]FrameworkId='WPF' && ControlType='Button' && AutomationId='closeWithoutSave' | Performed (4) searches, UI element not found
mtm.exe, Playback - {1} [FAILED] Function ElementFetcher::FindScreenElement failed to locate UI element (;[UIA]FrameworkId='WPF' && ControlType='Button' && AutomationId='closeWithoutSave') (Das angegebene Objekt wurde nicht gefunden.)
What is weird here is that I even set the Automation.AutomationID on that button and it still failed. Also I'm not sure if that is right but the search doesn't seem to include the name/automationID of the Window that has that button. Since I've, at that point, two windows open in the application I could imagine that being the problem.
I inspected the UI test that was generated by MTM by loading it into a Coded UI Test Project. I opened the UI Control Map and saw what was wrong:
The TabControl/TabPage navigation was grouped in the same Window as the ContextMenu of the TrayIcon.
The reason for that was, that instead of using the Name property of a WPF Window, MTM/Coded UI Tests use the Title property as the identifier of a Window (wtf?).
The Solution:
Setting the Title property of my WPF configuration window to Configuration and redoing the affected test steps solved the problem.
Hint for people with a similiar problem: It may also help to increase the MaxLevelsForItemContainer value in the mtm.exe.config file that is located in Common7\IDE of your Visual Studio installation folder.

MVVM Application not Restoring State Correctly

I have built a class library that acts as a GUI framework that can be inherited by other projects. This application is based on projects Wild and Gemini.
My problem is that upon restoring Avalon Dock's layout using the standard serializer
var layoutSerializer = new XmlLayoutSerializer(manager);
where manager is type DockingManager. The manager restores and empty tab. My guess is that Caliburn Micro cannot find the stored ViewModel (named HomeViewModel). However, I am struggling to confirm this.
I believe my bootstrapper to be correct and that the MEF containers are being setup correctly to allow resolution of external types. I have debugged the project to a point where I think this issue is occurring and in the output window I can see Attach(Home) where the attach is occurring (note, "Home" is the display name of the HomeViewModel). However, I don't know what is wrong with the attach process as this is handled by MEF/Caliburn.
I am really stuck with debugging this an wondered if
Any one could offer any insightful advice as to how to proceed with the debugging process?
Anyone would be willing to take a look at the solution?
I have spent a hell of a lot of time debugging this without any luck and the problem is sufficiently esoteric and illusive as to render most posts here irrelevant to me.
Thanks for your time.
as discussed and after looking on the sample code provided, I understand that the following
HomeViewModel or can say LayoutItemBase is not supposed to be reopened as ShouldReopenOnStartup is set to false
if you close the application while leaving a document open for HomeViewModel it is restored on next start with blank view [Not OK]
Analysis
the SaveState method was correctly honoring ShouldReopenOnStartup value and was not emitting the state for the HomeViewModel but dock manager was still emitting an element for the document.
So upon next restart the LoadState does not find any stored state but a window was created as an element was present in the dock manager's layout state
<LayoutDocument Title="HomePP" IsSelected="True" IsLastFocusedDocument="True" ContentId="d716f824-cfff-4b54-8fd6-2d026a99369a" .../>
you did try to use e.Cancel property of Serialization callback to cancel the event, but seems like it is not supposed to prevent of loading a window but just simply to cancel the event if not needed.
Resolution
So the ideal approach is to close the documents which are not supposed to be restored before saving the layout
here is how I did
ShellViewmodel.cs : Line 279 method SaveState(string)
change the following code
if (!item.ShouldReopenOnStartup)
continue;
to
if (!item.ShouldReopenOnStartup)
{
//this item is not supposed to be restored so close the window before saving layout
IDocument doc = item as IDocument;
if (doc != null)
CloseDocument(doc);
continue;
}

Creating a Visual Studio style errors tool window with jump to error functionality

I'm using Caliburn Micro to create a Visual Studio style interface for my application.
The user could have multiple errors in multiple windows which are all shown on an 'errors' view which is docked at the bottom of my application. I've managed to implement a nice notification mechanism so that when changes are made to any document, the errors VM is notified and queries the source object.
I'm having trouble, however, in figuring out how to get a double-click to navigate to the source of the error.
Imagine I have bound 'description' to a textbox on my document view and this provides a 'description is required' validation message. Double clicking the message should navigate the user to the document in question and focus on the textbox.
The validation objects that provide the messages already contain a reference to the viewmodel (as an IViewAware interface) which allows me to call GetView() to get a reference to the view. I've tried using this approach to enumerate the bindings on my view and find the controls that are bound to a particular property, though this is very slow and more of a brute force - pot luck approach
Does anyone have any recommendations on approaches to this problem? My only other thought is to pass responsibility of the 'focus' action to the view itself and have that decide how to handle a request for navigation to a certain property - maybe using attached properties to identify particular controls by a unique property identifier. The application could cache this list in a dictionary to make things quicker (all the processing done up front as the app is loading)
I assume Visual Studio implements this quite easily for the standard code editor window, since it just needs a line number to jump to the right place..
Ok so after a couple of hours messing about with this I've come to a solution which seems to work ok. I've implemented an interface class for my views which allows them to navigate.
The basic setup is:
ErrorsViewModel - receives notifications that a business object needs requerying for errors and manages the list of errors and when it needs to query (so that any work can be done on a background thread to prevent locking the UI)
WorkspaceViewModel - the main workspace VM that hosts the tool panes and documents
ICanNavigate - interface that the views will impelement to decide how to handle navigation arguments
NavigationEventMessage - the message that is sent to the event aggregator to provide a navigation notification and arguments
The ErrorsViewModel receives an event message from another VM via the event aggregator and eventually queries the object (when it can). Once the errors are gathered, it shows the items in the view (in a grid control at the moment).
When the user double clicks on a row a NavigationEventMessage is dispatched which contains some arguments such as the view that dispatched it and the target business object etc. It is handled by..
1) The WorkspaceViewModels view. This allows it to bring the correct document into activation by looking at the DataContext of each object and checking if it matches the view passed in the message
2) The target documents view, the view decides what to highlight/show/seek to based on the arguments sent in the message
This seemed to be the most logical way to separate the VM from the View as the ViewModels still have no coupling with the views. The view just implements the interface, and the VM calls it if it's there and passes in the args.

How to know what file fails during WPF Binding

I've read a lot of questions on SOF and links (for example http://www.beacosta.com/blog/?p=52)
But is there easy way to know what exact file I should look into when Binding fails?
If we have one Application and a lot of forms, it can be difficult too.
Have you tried checking "Thrown" for the exception in question in the Debug->Exceptions menu.
E.g. if you get
System.Windows.Data Error: 35 : BindingExpression path error ...
Then you can tell the debugger to break on it by checking "Thrown" under Common Language Runtime Exceptions -> System.Data -> System.DataException. This is however, only useful if the exception originally occurs in your code. Other exceptions, such as binding to non-existing properties and so on will silently fail and only print in the Output window. There is some discussion on http://visualstudio.uservoice.com for improving XAML debugging
I just found the most WONDERFUL post when looking for this. It is a listener that listens for binding errors and throws up a message box with details. It only works when running from within Visual Studio, so you won't show it to your users. Two steps - copy the class into your project, and set the listener in your main window.
http://tech.pro/tutorial/940/wpf-snippet-detecting-binding-errors
You can use Snoop for this: http://snoopwpf.codeplex.com/
Just use Snoop to point to your application and then you can sort on Binding Errors. All Bindings Errors will be highlighted in RED, and show the property of the control.

Adding a user control "The Enumerator is not valid"

I'm using Visual Studio 2010 to create a small WPF application. I've created a user control that I am now trying to add to my main form. The user control does show up in toolbox but every time I try to drag the control to the form I get the error:
The enumerator is not valid because the collection changed.
I should know what's wrong and it is bugging me that I can't figure it out.
You have a bug in the constructor of the usercontrol - you are using a foreach-loop over an IEnumerable and while the loop is running, the IEnumerable is changed, this is not allowed with a foreach loop. Use a for loop instead if you are manipulating the Collection you are iterating over.
The problem here is that you don't know what code is throwing the exception.
WPF is terrible about exceptions, especially in constructors. The framework insists on catching and re-throwing a new exception, usually multiple times, and it's difficult to find the original stack trace. I've found the easiest way to track down this kind of error is to tell Visual Studio to stop as soon as the exception is thrown, rather than waiting until WPF has re-thrown it a couple of times and made the details difficult to dig out.
I don't have Visual Studio 2010 in front of me, but here's how to do this in VS2008 -- 2010 is probably similar:
Go to the Debug menu > Exceptions...
Next to "Common Runtime Language Exceptions", check the box in the "Thrown" column
Then debug your app again. It will stop at the line that's actually causing the problem, and it'll be much easier for you to see what's going on. And if you're still not sure why it's throwing an exception, you'll be able to post a code sample.
In order for a user control to function properly you need to have a constructor that takes zero arguments. This way the form designer has a way to render the control in a "default" manner.
I then overloaded my constructor to take the arguments I needed to actually run the control properly and everything worked as expected.
You need to:
Remove the DLL reference
Add a reference to your control
Rebuild the solution
Add your control. It should work!

Resources