• Welcome to Valhalla Legends Archive.
 

PropertyGrid + Reflection.

Started by K, July 18, 2004, 02:24 PM

Previous topic - Next topic

K

If you haven't used it before, the .NET Property Grid is a wonderful tool.  Write a class, add some attributes, and bind the PropertyGrid to your object.  voila:





quasi-modo

ooo sexy. I do not use vb.net for executable ap programming though :x
WAR EAGLE!
Quote(00:04:08) zdv17: yeah i quit doing that stuff cause it jacked up the power bill too much
(00:04:19) nick is a turtle: Right now im not paying the power bill though
(00:04:33) nick is a turtle: if i had to pay the electric bill
(00:04:47) nick is a turtle: id hibernate when i go to class
(00:04:57) nick is a turtle: or at least when i go to sleep
(00:08:50) zdv17: hibernating in class is cool.. esp. when you leave a drool puddle

MyndFyre

Quote from: K on July 18, 2004, 02:24 PM
If you haven't used it before, the .NET Property Grid is a wonderful tool.  Write a class, add some attributes, and bind the PropertyGrid to your object.  voila:



That was one of the things I was having trouble with -- how do you get non-enumeration values inside of a field?  Or any other selector (like a CSS designer you see in Visual Studio) on a property?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

K

#3
Here's the code for the little drop-down server list:


// Settings class
// ...
[
  Category("Connection"),
  // the following line is required for the drop down functionality
  TypeConverter(typeof(ServerList)),
  /* more attributes... */
  DefaultValue("useast.battle.net"),
  Description("Enter the hostname or IP address of the server you would like to connect to, or select one from the drop down box.")
]
public string Server
{
   get { return _Server;}
   set { _Server = value; }
}



and here is the ServerList class:


using System;
using System.ComponentModel;

// since the choices are strings, I derived from the StringConverter.
public class ServerList : StringConverter
{
  // made static.  Good idea.
   protected static string[] _servers = new string[]
   {
      "useast.battle.net",
      "uswest.battle.net",
      "europe.battle.net",
      "asia.battle.net"
      /* etc */
   };

   // simply return your wrapped array
   public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
   {
      return new StandardValuesCollection(_servers);
   }

   // return false: combo box (can enter own value)
   // return true: listbox (cannot enter own value)
   public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
   {
      return false;
   }

   public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
   {
      return true;
   }
}



if you want to be able to show a custom string representation of a custom contained class (as well as edit its properties) like so:



you need to:
1) give the contained class the [TypeConverter(typeof(ExpandableObjectConverter))] attribute
--(no custom string representation or setting properties by modifying the custom string)

or
2) create a class that inherits ExpandableObjectConverter like so:


public class KarmaUserConverter : ExpandableObjectConverter
{
   public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
   {
      if (destinationType == typeof(KarmaUser))
         return true;

      return base.CanConvertTo(context, destinationType);
   }

   public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,  Type destinationType)
   {
      if (destinationType == typeof(System.String) &&
         value is KarmaUser)
      {
         KarmaUser ku = (KarmaUser)value;

         return ku.Name + (ku.Admin ? " (admin)" : "");
      }
      return base.ConvertTo(context, culture, value, destinationType);
   }
}


(the above example does not parse the custom string if it's changed.  you need to implement ConvertFrom() and CanConvertFrom() if you want to do that.)

MyndFyre

Quote from: K on July 19, 2004, 09:03 PM

   protected string[] _servers = new string[]
   {
      "useast.battle.net",
      "uswest.battle.net",
      "europe.battle.net",
      "asia.battle.net"
      /* etc */
   };


Thank you much.  :)

Here's a thought I had: would it be possible to make this static?


  protected static string[] _servers = new string[]
  {
     "useast.battle.net",
     "uswest.battle.net",
     "europe.battle.net",
     "asia.battle.net"
     /* etc */
  };


That way there is only one reference to the array versus multiple references to the array?

Just a thought, thanks for the info.  :)
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

K

#5
As a side note, my last screen shot is really cool.  It lets the user load any of the .xml configs generated by my bot or plugins, then finds the assembly that that settings class is declared in, finds the settings class and insantiates it through reflection to load / display / save the settings.

For example, in the screen shot, I chose karma_config.xml (settings for the Karma plugin), the application found the PlugDev.KarmaSettings class in Karma.dll and loaded the assembly to parse the xml file.
fun!