Friday, August 22, 2008

Adding an inherited custom control into Visual Studio Toolbox

Let's say we created the base control XPanel:
   public class XPanel : Panel
   
and its descendant XFinalPanel:
   public class XFinalPanel : XPanel
   
We are to show the XFinalPanel control in the Toolbox and to hide the XPanel. By default both controls should be visible in the Toolbox. There is a ToolboxItem attribute that allows to manage the control visibility. As it is inherited, it sounds logical to write the following code to solve the task:
   [ToolboxItem(false)]
   public class XPanel : Panel
   ...
   [ToolboxItem(true)]
   public class XFinalPanel : XPanel
Unfortunately, it doesn't work. The XFinalPanel is shown in the Toolbox, but you can't drag&drop it to the form. The only workaround I've found is to declare XPanel as abstract class. Or, of course, you may let both controls be shown in the toolbox.

Friday, August 8, 2008

'could not be set on property' error in custom ASP.NET controls

XPanel class in our EasyQuery.NET WebForms project contains the Appearance property of complex type XAppearance. This class has another "complex" property MenuStyle so we got a complex property inside another complex property:
 
public class XPanel : Panel, INamingContainer {
     .  .  .  .  .  .  .  .  .  . 
     private XAppearance appearance = null;

  [DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
      NotifyParentProperty(true)]
  public XAppearance Appearance {
      get {
             return appearance; 
         }
  }
     .  .  .  .  .  .  .  .  .  . 
}

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .

[TypeConverter(typeof(ExpandableObjectConverter))]
public class XAppearance : IStateManager {
    .  .  .  .  .  .  .  .  .  . 
    
 private ScriptMenuStyle scriptMenuStyle;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
     NotifyParentProperty(true)]
    public ScriptMenuStyle ScriptMenuStyle {
        get {
            return scriptMenuStyle;
        }
    }
    .  .  .  .  .  .  .  .  .  . 
}

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .

[TypeConverter(typeof(ExpandableObjectConverter))]
public class ScriptMenuStyle : Style {
    .  .  .  .  .  .  .  .  .  . 
}

Everything will work OK at run-time. But if you try to change some sub-property of XPanel.Appearance.MenuStyle in visual designer then next time you load this form, Visual Studio will show you the following error message:
"SomeValue" could not be set on property SomeProperty
We have spent several hours trying to find the reason of this error message without any success. Finally we have found the solution but still do not know the source of the problem. The solution is quite simple. We just need to make ScriptMenuStyle property writable:
 
[TypeConverter(typeof(ExpandableObjectConverter))]
public class XAppearance : IStateManager {
    .  .  .  .  .  .  .  .  .  . 
    public ScriptMenuStyle ScriptMenuStyle {
        get {
            return scriptMenuStyle;
        }
  set {
      scriptMenuStyle = value;
  }
    }
    .  .  .  .  .  .  .  .  .  . 
}
Now everything works correctly both at run-time and at design-time but it will be great to get known what was the cause of this problem.