Hi everyone,
(I already posted this to the VS.NET IDE news group without any responses, so I'm attempting one more time in this group)
The issue I'm having is occuring in the IDE of VS.NET 2003, although I'm not sure what is actually causing the problem. I can't
summarize the issue, so please read on to find out more.
I've created a BaseDialogEditor class that allows a developer (namely me) to create Modal editors for controls at design time
without having to rewrite the same "EditValue" logic and "Form" logic again. The class derives directly from UITypeEditor.
The BaseDialogEditor has an abstract property called "BaseDialogType" that defines the Type of Form that will be displayed. The
form must derive from BaseDialogEditorForm, which is also abstract. The base form has an OK and Cancel button, complimentary
events, and the Form properties set up appropriately so the Form will appear as a Modal Dialog. (Derived implementations may change
this when necessary)
Here is a snippet from the EditValue override of the BaseDialogEditor class (I've added comments to guide you through the steps):
try
{
// type is a local variable, assigned to the abstract "Type" property, which returns a Type instance.
// I've already insured that type is a BaseDialogEditorForm, using reflection, before this code is reached.
gui = Activator.CreateInstance(type) as BaseDialogEditorForm;
}
catch (Exception ex)
{
throw new SynthesoftException("Cannot create instance of DialogFormType Type. There may be no default constructor.",
"BaseDialogEditor.EditValue", ex);
}
try
{
context.OnComponentChanging();
// This allows derived BaseDialogEditor classes to modify "value" before it's passed to the form
OnBeforeEdit(context, provider, value);
// The BaseDialogEditorForm has a virtual method called, "Initialize" where it can store the information it needs to display:
gui.Initialize(context, provider, value);
[...]
Here is the entire "BaseDialogEditorForm.Initialize" code block:
public virtual void Initialize(System.ComponentModel.ITypeDescriptorCo ntext context, IServiceProvider provider, object component)
{
// Assign the local variables to the parameters passed in by the BaseDialogEditor class.
// Each variable has a public property that allows derived implementations to access them at runtime.
this.component = component;
this.provider = provider;
this.context = context;
}
I've created an editor deriving from BaseDialogEditor and a Form deriving from BaseDialogEditorForm and setup everything
appropriately.
I'm able to successfully use the editor at design time, and it works as expected, except for one important thing; Derived classes
cannot access the three local variables mentioned above.
To see why I was getting an InvalidCastException thrown when accessing the variables, I ran a new instance of VS.NET and attached to
it using the first instance of VS.NET (both 2003).
In the debugger, I set a break point on:
this.component = component;
When I clicked the elipses on my property in the VS.NET PropertyGrid, the debugger stopped at that line, as I expected.
The Type of component that appeared in the tooltip and Watch windows was correct. It was the Type that I was trying to edit.
I stepped to the next line:
this.provider = provider;
I moused over "this.component" to ensure that the variable took the parameter's value, but to my suprise it was "<undefined value>"
I've never seen this happen before.
I opened the command window in immediate mode:
this.component
<undefined value>
this.component == null
false
this.component.GetType()
error: 'this.component.GetType' does not exist
(object) this.component
<undefined value>
Can anyone explain how a variable is not "null", yet cannot be cast to System.Object?
To make things even stranger, I queried the public property that has "this.component" as a backing field:
Value
<error: an exception of type: {System.ArgumentException} occurred>
The public property is called "Value". It has one line of code in the get accessor:
return component;
So, where is the ArgumentException coming from?
Furthermore, as soon as I entered "Value" into the immediate window, I saw the watch on "this.component" change from "<undefined
value>"
to the appropriate Type with a "+" sign to drop it down. It seems that querying the "Value" property forced the "component" field
to show it's real value. How is that possible?
Now, in the immediate window and watch window everything seemed fine. The same was true for the other two variables I mentioned
above in the "Initialize" method as long as I queried their public properties first.
Obviously, this won't do since I can't attach a debugger everytime I need the editor to work correctly!
The first attempt to use my editing framework worked without a problem since I didn't have a need to query those variables. The
issue went unnoticed until I actually needed those values in a different property editor and got InvalidCastException when
attempting to cast the public properties of those variables at runtime to the Type I expected to be returned.
As for assembly references, both instances of VS.NET (the debugger and the testing instance) reference the exact same assembly that
contains the code mentioned above. The assembly built successfully before starting the project in debug mode.
Can anyone shed a little light on the issue at hand?
Thanks in advance,
--
Dave Sexton
dave@www..jwaonline..com
-----------------------------------------------------------------------