Passing objects to a UITypeEditor
Asked Answered
D

2

5

I am currently hoping to use a PropertyGrid to allow users to edit some of my classes, however I've hit a wall with passing objects to the UITypeEditor(s) they use. When the user presses the drop down I want to show a listbox of already loaded textures to choose from, if they want to use a texture the application hasn't loaded yet they can click a button to choose one from a file dialog. In case I make no sense here a mock of the form:

Dropdown Image.

My problem: To fill the listbox I need access to the class that manages the list of resources from the UITypeEditor.

Now I've solved this problem for my own classes by giving them a reference on creation to their managing object. In the UITypeEditor I then use that reference to access what I need. However I can't do this for classes I haven't written, such as the XNA Texture2D class.

Here are what the classes I'm using look like:

class StaticGeometryChunk
{
    // Geometry data to draw with. Contains a reference to its managing 
    // class for use in its UITypeEditor.
    public GeometryData { get; set; }
    ....
}

class Material
{
    // These are XNA classes. I can't just add a reference to its managing 
    // class (I think?).
    public Texture2D Texture1 { get; set; }
    public Texture2D Texture2 { get; set; }
    ....
}

I've been looking at my options and they seem to be:

  1. Make the managing classes static.

I don't really want to do this. There are several managing classes as each resource is loaded differently. There are also classes that need to be created before these and are passed in.

  1. Make the managing classes singletons.

I don't really want to do this either. It seems like a quick and dirty way to "hide" the problem instead of "solve" it. I also might want the option of having several managing classes in the future which the singletons eliminate.

  1. Create a wrapper class which holds the reference to a managing class and its target (such as the XNA Texture2D).

This is currently what I'm thinking of doing. Its would be quite simple and quick to do but something about it nags me but I don't know what.

Any thoughts on the above or other methods to pass what I need into the UITypeEditor?

Thank you for reading.

Danit answered 18/6, 2009 at 3:18 Comment(0)
B
8

In the EditValue method, you are given a context. Use context.Instance to access the object that holds your property. This object should also contain a property that gives you access to the list of things you want to display. You could test if context.Instance is ITextureProvider for example, then cast it and access the textures. Not sure if this makes sense in your design but let me know.

Blasien answered 18/6, 2009 at 12:20 Comment(3)
My current design looks like this: MaterialDatabase: Holds a dictionary of Materials which contain the Texture2D classes. GeometryDatabase: Holds a dictionary of StaticGeometryChunks which contain the GeometryData. TileDatabase: Holds a dictionary of Tiles which contains a StaticGeometryChunk and a Material. When these classes are created they are passed a treeview to display what they have loaded, its a selection on the treeview that triggers the propertygrid to view the nodes tag (a reference to the dictionary object). I have a feeling this means the context will be the treeview?Danit
Sorry my formatting has disappeared above and I ran out of characters. Thanks for the reply. The main overall class is the Tile, they use the other two objects (Materials/Geometry) for its data. This is so that if a user changes a texture in a material, all of the Tiles using that material get the change too. Could a slight redesign of this setup make my it easier?Danit
context.Instance is the owner of the property. In your case, it would be Material. So, this Material class should be able to access the possible textures.Blasien
B
4

As an alternative you can try the following approach. I find it very elegant, because it does not require to store a list of available property values in the object. Therefore, for example, you can show one set of values on one form and another set on another.

  1. Create an interface IYourDataProviderService.
  2. Create an implementation of IYourDataProviderService, which knows the concrete data to provide.
  3. Create a class implementing ISite. In GetService() method return an instance of class which implements IYourDataProviderService, if the serviceType parameter is typeof(IYourDataProviderService). I left rest of ISite methods throwing NotImplementedException (except DesignMode property) and for me it worked, but probably this is not an ideal solution.
  4. In 'Load' event handler assign your implementation to the Site property of your propertygrid.
  5. Enjoy!
Bitumen answered 19/5, 2010 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.