This message was discovered on microsoft.public.dotnet.framework.windowsforms.designtime.
| Nathan Baulch |
I have two assemblies. Assembly1 is a DLL that has a custom control with a property of type System.Type. Assembly2 is an EXE that has a form with an instance of that control on it. In the Properties of that control, I want a custom drop-down to display all types in Assembly1 that extend Form.
I have extended UITypeEditor as per usual but I'm having a lot of trouble finding an Assembly object reference for Assembly1.
The following static calls from within the EditValue method: Assembly.GetCallingAssembly() Assembly.GetEntryAssembly() Assembly.GetExecutingAssembly() return: System.Windows.Forms null Assembly1 respectively.
I have also tried Context.Container.GetType().Assembly Context.Instance.GetType().Assembly with no luck.
Is this even possible?
Nathan
|
|
|
| |
|
| |
| |
| Günter Schwaiger |
Hi, Solution 2: You have the instance of the Control, so you have the Parent of the Control (YourForm) and if the parent is defined in assembly2 you get the assembly from the Type of the Parent.
control.Parent.GetType().Assembly
HTH Guenter Schwaiger
"Nathan Baulch" <Click here to reveal e-mail address> schrieb im Newsbeitrag news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
| |
| |
| Nathan Baulch |
> control.Parent.GetType().Assembly
I'm afraid this doesn't work either. Sorry to bore you with the details, but I'm going to have to explain my setup a little further.
Assembly1 (DLL) contains MyCustomEditor : UITypeEditor MyCustomControl : Control MyCustomForm : Form
Assembly2 (EXE) contains MyForm1 : MyCustomForm MyForm2 : MyCustomForm MyForm3 : MyCustomForm
MyCustomControl contains a System.Type property called EditForm with MyCustomEditor as its editor. MyForm1 has an instance of MyCustomControl placed on it. When editing the EditForm property of this control, I want to list the names of all classes that extend MyCustomForm in the assembly containing the form that the control is on. In this case, I would want it to display: MyForm1 MyForm2 MyForm3
The confusing part is that your idea: ((Control)Context.Instance).Parent returns MyCustomForm and not MyForm1 which I don't understand.
|
|
|
| |
|
|
| |
| |
| DRaiko |
Hi Nathan,
That's strange, but inavitable. At Design time your Assembly simply doesnt exist as a complete assembly. You are only going to create it. The assembly that runs, is VS + standard designer + you designer (the assembly list in you mail 2004-02-03 15:58:21 PST evidences this). And the target assembly you are going to create may have errors, etc. It is not compiled yet.
There is a different representation of the target assembly. You can access it through _DTE. There you get no Reflection.Types but something alike -- EnvDTE.CodeClass. You can not instantiate them, [to be more precise: i don't know how to instantiate them, but i have greate doubts that this is even in principle possible] since they also are not compiled, may have errors, etc. But you can still get some information about them (IsAbstract, IsDerivedFrom, ImplementedInterfaces, Bases, etc.).
If you are sure, that the old (already compiled) version of your ..exe is good for you, you can load the result of the project (EnvDTE makes it possible to find the file name, but dont ask me how) and instantiate the type. So, it depends on what do you whant to do with the type you are looking for: EnvDTE can help.
In your mail of 2004-02-03 16:34:24 PST you write: [Original message clipped]
The reason is the same. The Designer can not use MyForm1 as the parent for your controls. It is not compiled yet (and an older version may not be used, since you may have change the text essentially). The only chance for the designer (and it takes it) is to use the form's base MyCustomForm and to interpret the InitializeComponents(). Interpreting InitializeComponents() replaces the compilation in some way (and what else can you suggest?).
Note that if you use the same code to examine assemblies in you runtime classes, you get a quite different result -- at runtime the parent of controls is MyForm1, as one can expect.
I add a piece of code here (i know, a poor style, there are better ways,...) but: (i) it runs; (ii) it still may make your research in EnvDTE Namespace shorter.
Regards, Dima.
// List all types derived from _rootType public abstract class IheritedTypeNameConverter: StringConverter{ private Type _rootType; // is also misused as a flag: // "Do we already have the _stdValues list?" private StandardValuesCollection _stdValues;
// override this returning the type you need. protected abstract Type RootType{ get; }
protected virtual bool IncludeAbstract{ get{ return false; } }
public override bool GetStandardValuesSupported( ITypeDescriptorContext context) { return true; } public override bool GetStandardValuesExclusive( ITypeDescriptorContext context) { return true; }
public override StandardValuesCollection GetStandardValues( ITypeDescriptorContext context) { if( _rootType == null){ _rootType = this.RootType; if( _rootType == null) throw new ApplicationException( "Can not list types inherited from <null>.");
_stdValues = new StandardValuesCollection( this.MakeTypeList( context)); } return _stdValues; }
private ICollection MakeTypeList( ITypeDescriptorContext context){ StringCollection ret = new StringCollection();
EnvDTE._DTE dte = (EnvDTE._DTE)context.GetService( typeof( EnvDTE._DTE)); if( dte == null) throw new ApplicationException( "Can not get _DTE from context.");
foreach( EnvDTE.Project prj in dte.Solution.Projects){ VSLangProj.VSProject vsprj = (VSLangProj.VSProject)prj.Object; EnvDTE.CodeModel codeModel = prj.CodeModel; if( codeModel != null){ this.FindTypesInDteCodeModel( ret, codeModel.CodeElements, _rootType.FullName); } } return ret; }
// appends all classes found to its 1st arg. private void FindTypesInDteCodeModel( StringCollection lst, EnvDTE.CodeElements codeElements, string fullName){ foreach( EnvDTE.CodeElement celm in codeElements){ EnvDTE.CodeNamespace ns = celm as EnvDTE.CodeNamespace; if( ns != null) this.FindTypesInDteCodeModel( lst, ns.Members, fullName); else{ EnvDTE.CodeClass ccl = celm as EnvDTE.CodeClass; if( ccl != null){ if( (!ccl.IsAbstract || this.IncludeAbstract) && ccl.get_IsDerivedFrom( fullName)) lst.Add( ccl.FullName); this.FindTypesInDteCodeModel( lst, ccl.Members, fullName); } } } }
"Nathan Baulch" <Click here to reveal e-mail address> wrote in message news:<#Click here to reveal e-mail address>... [Original message clipped]
|
|
|
| |
|
| |
| |
| Richard Petheram |
Hi Dima,
Thanks for the code - it was useful. Just to contribute my 2p worth, here's a (somewhat messy) VB class I derived from your code. I'm using it to create a list of forms that have either the user defined WebPopupDialogAttribute or WebPopupWindowAttribute. In my code these represent windows that can be used as popups, and the attributes carry information about size, position, scroll bars etc.
Regards
Richard
[ CODE FOLLOWS ]
Public Class PageTypeNameConvertor Inherits System.ComponentModel.TypeConverter
Private mValues As StandardValuesCollection
Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection Dim lColl As New Collection Dim lDTE As EnvDTE.DTE Dim lCodeModel As EnvDTE.CodeModel Dim lCodeElem As EnvDTE.CodeElement Dim lCodeClass As EnvDTE.CodeClass Dim lAttrbs As EnvDTE.CodeAttribute
If mValues Is Nothing Then lDTE = CType(System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE"), EnvDTE.DTE) For Each lProjectWrapper As EnvDTE.Project In lDTE.Solution.Projects lCodeModel = lProjectWrapper.CodeModel For Each lCodeElem In lCodeModel.CodeElements Try lCodeClass = CType(lCodeElem, EnvDTE.CodeClass) For Each lAttrbs In lCodeClass.Attributes If lAttrbs.FullName = GetType(WebPopupDialogAttribute).FullName Or _ lAttrbs.FullName = GetType(WebPopupWindowAttribute).FullName Then lColl.Add(lCodeClass.FullName) Exit For End If Next Catch End Try Next Next mValues = New StandardValuesCollection(lColl) End If Return mValues End Function Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean Return True End Function Public Overloads Overrides Function GetStandardValuesExclusive(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean Return True End Function End Class
-------------------------------- From: Richard Petheram
|
|
|
| |
|
| |
|
| |
| Jeroen van Helvoort |
Hi,
I have problems with the use of get_IsDerivedFrom(). When using my own code (or yours in your e-mail message) as part of a DLL which is referenced in a project, it works fine referencing it in a C# or J# project, but NOT in a VB project. I use the code to fill a listbox UITypeEditor, but when opening the listbox I get an exception with message "unspecified error" with source "EnvDTE".
During debugging it works fine in VB too!?
Any idea how to solve this? Thanks in advance.
Regards,
Jeroen
-------------------------------- From: Jeroen van Helvoort
|
|
|
| |
|
|
| |
|
|
|
|
| |
| Günter Schwaiger |
Hi Nathan, try do list all assemblies in the AppDomain, there assembly2 has do be found.
AppDomain.CurrentDomain.GetAssemblies()
HTH Guenter Schwaiger
"Nathan Baulch" <Click here to reveal e-mail address> schrieb im Newsbeitrag news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
| |
| |
| Nathan Baulch |
[Original message clipped]
Would you believe it's not there?
Accessibility Assembly1 Assembly3 COM2InteropEmit CustomMarshalers EnvDTE Microsoft.VSDesigner Microsoft.VisualStudio Microsoft.VisualStudio.Designer.Interfaces System System.Data System.Design System.Drawing System.Drawing.Design System.Windows.Forms System.Xml VSLangProj mscorlib
My solution has 3 projects and thus I would expect all 3 of their assemblies to be resident in Visual Studios Domain Assembly collection. Obviously this is not the case!
Perhaps I could send you an example solution?
|
|
|
| |
|
| |
| |
| Günter Schwaiger |
> Perhaps I could send you an example solution? Ok, send me the example solution. Guenter Schwaiger
|
|
|
| |
|
|
| |
| |
| Günter Schwaiger |
Hi Nato, now I understand your problem, it's really strange!
In the EditValue function only the base type of the form exists, so I asked me, how should MyCustomForm know who is inheriting it. I tried out to implement a virtual property Descendant and override it in MyForm1, but in EditValue allways the property of MyCustomForm is called.
public class MyCustomForm : System.Windows.Forms.Form { public virtual Type Descendant { get {return typeof(MyCustomForm);} } }
....
public class MyForm1 : Assembly1.MyCustomForm { public override Type Descendant { get {return typeof(MyForm1);} } }
.... EditValue
MyCustomForm cf = ((Control)Context.Instance).Parent as MyCustomForm; Type t = cf.Descendant; MessageBox.Show("The parent of the current control is:\r\n" + t.FullName);
IDesignerHost host = (IDesignerHost)Provider.GetService(typeof(IDesignerHost)); if (host != null) { foreach(IComponent component in host.Container.Components) { Debug.WriteLine(component.GetType().FullName); }
}
MyCustomControl is added to the MyCustomForm.Controls collection (inherited) and at design time MyForm1 is not used from the Visual Studion Designers.
For the moment I have no idea how your problem could be solved.
Regards
Guenter Schwaiger
|
|
|
| |
|
| |
|
|
|
|
| | |
|
|
|
|