简体   繁体   中英

Is it possible to control how IExtenderProvider formats the output in the Windows Forms Designer code?

I have a class that implements IExtenderProvider

Here is a great article about that interface http://www.codeproject.com/Articles/4683/Getting-to-know-IExtenderProvider

The basic idea is to select a control in the windows forms desinger and have a "virtual" property MyProperty on MyExtender

The tooltip does the same.

This works as expected and the designer code looks like this

this.label1.AutoSize = true;
...
this.myExtender1.SetMyProperty(this.label1, "MyValue");
...
this.label1.Name = "label1";
this.label1.Text = "label1";

It is only allowed to input resource strings from a specific resource file via a drop down menu in the property grid. Now what I want to achive is this

this.label1.AutoSize = true;
....
this.myExtender1.SetMyProperty(this.label1, 
                 My.Namespace.Properties.Resources.MyValue);
...
this.label1.Name = "label1";
this.label1.Text = "label1";

which is the reference to the string variable in my resource class. The idea is that I want to profit from the static typing (If I rename a resource I get design time errors rather than runtime errors).

Is there a way to achive this?

This article titled " Bending the code generation of IExtenderProvider to your will " by Tim Van Wassenhove may solve your problem.

It states:

In Exploring CodeDomSerializer i already explained how we can modify the code that the Visual Studio designer generates for us. With a typical IExtenderProvider the designer generates an initializer, SetXXX methods and a variable declaration...

Now, what if we're not happy with those generated SetXXX methods on each Component? The problem is that this code is not generated by the serializer for the ConstantsExtenderProvider but by the serializers for the Components. An easy workaround for this problem is to set the DesignerSerializationVisibilityAttribute on the GetXXX method in our IExtenderProvider to Hidden .

With those ugly SetXXX methods out of the way it's up to us to do it better. We do this by implementing a custom serializer for our ConstantsExtenderProvider:

class ConstantsSerializer<t> : CodeDomSerializer
{
 public override object Serialize(IDesignerSerializationManager manager, object value)
 {
  ConstantsExtenderProvider provider = value as ConstantsExtenderProvider;
 
  CodeDomSerializer baseClassSerializer = manager.GetSerializer(typeof(ConstantsExtenderProvider).BaseType, typeof(CodeDomSerializer)) as CodeDomSerializer;
  CodeStatementCollection statements = baseClassSerializer.Serialize(manager, value) as CodeStatementCollection;
 
  IDesignerHost host = (IDesignerHost)manager.GetService(typeof(IDesignerHost));
  ComponentCollection components = host.Container.Components;
  this.SerializeExtender(manager, provider, components, statements);
 
  return statements;
 }
 
 private void SerializeExtender(IDesignerSerializationManager manager, ConstantsExtenderProvider provider, ComponentCollection components, CodeStatementCollection statements)
 {
  foreach (IComponent component in components)
  {
   Control control = component as Control;
   if (control != null && (control as Form == null))
   {
    CodeMethodInvokeExpression methodcall = new CodeMethodInvokeExpression(base.SerializeToExpression(manager, provider), "SetConstants");
    methodcall.Parameters.Add(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), control.Name));
 
    string[] constants = provider.GetConstants(control);
    if (constants != null)
    {
     StringBuilder sb = new StringBuilder();
     sb.Append("new string[] { ");
 
     foreach (string constant in constants)
     {
      sb.Append(typeof(T).FullName);
      sb.Append(".");
      sb.Append(constant);
      sb.Append(", ");
     }
 
     sb.Remove(sb.Length - 2, 2);
     sb.Append(" }");
 
     methodcall.Parameters.Add(new CodeSnippetExpression(sb.ToString()));
    }
    else
    {
     methodcall.Parameters.Add(new CodePrimitiveExpression(null));
    }
 
    statements.Add(methodcall);
   }
  }
 }
}

And now the generated code looks like:

this.constantsExtenderProvider1.SetConstants(this.button1, new string[] {
    WindowsApplication1.Constants.Operation1,
    WindowsApplication1.Constants.Operation5
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM