I'm using a custom dynamic class object in a PropertyGrid (too much code to post here). In a nutshell, what it does is allow me to create properties at run-time from arbitrary input (in this case XML but that's beside the point). These properties may be any type, including another custom class so they can be nested indefinitely.
The issue I'm having is that the PropertyGrid sees this class as a Collection, and has the button in the Value column that allows you to open the CollectionEditor. This (among other things) has Add and Remove buttons, both of which will fundamentally break the custom class. Rather than try and make these two complicated systems work together nicely, I'd rather simply disable the CollectionEditor altogether. I have another system which allows you to see the child objects of the class (by setting the PropertyGrid.SelectedObject to the child object) and it works fine. I'd prefer the user not even having the option of seeing the CollectionEditor, as it seems to be not at all compatible with this system.
Ideally, I'd like to just put a button in the Value column that I could capture a click-event and handle myself, but that's optional. I also don't care if I disable the CollectionEditor for just the row(s) in question or for the whole PropertyGrid. I'm not using it either way, so anything which just makes it not accessible would be good.
Have you tried deriving your own CollectionEditor and in there override some methods/events to make its form not appear and just return without doing anything?
You then need to mark your collection type properties with:
[EditorAttribute(typeof(MyCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
This will automatically launch your MyCollectionEditor when clicking on the "..." button for the marked collection property in the PropertyGrid.
You may also need to inherit PropertyDescriptor and override the GetEditor method to return your own CollectionEditor.
Related
I have inherited user controls in the following manner:
ControlBase
|__ControlInherited1
|__ControlInherited2
ControlBase contains methods and properties that are overridden in each inherited control, but it has no other controls at all. Inherited controls override the base methods and have sub-controls on them and totally different from each other.
I have the ControlBase added to the form, and I want to change it to either ControlInherited1 or ControlInherited2 depending on run-time conditions.
I'd like to take advantage of the inheritance so I do not have to add different routines for every inherited class
I tried the simple controlBase = new ControlInherited1(); line, but the objects of ControlInherited1 control is not displayed on the form.
Is such visual inheritance even possible?
The problem you have is that even if your new control is inherited from the base control, there's no automatic way of applying the existing properties to the new one you're adding with the call controlBase = new ControlInherited1();. In essence, you'll lose all information about the original control when overwrite the original variable by creating a new instance of the ControlInherited1 class and setting it as the value of controlBase.
The correct way to replace an existing control would be to first remove the existing control and then adding the other one to the form, like following:
this.Controls.Remove(controlBase);
this.Controls.Add(newControl);
On top of this, you'll have to do some manual work to make sure all the properties that you want to persist from the original control are applied to the new (replaced) one.
I have an existing custom control library with controls which may contain properties: HeaderStyle, ModalStyle, Collapsable, etc...
In the user interface the program is currently displaying a categorized list of these properties. I am trying to update this code to hide properties they dont normally use. I have a list of properties to hide/show based on button click but I am not sure how I can hide these fields programmatically.
I would like to retain any values entered into the fields before hiding and re-display the values if the fields are shown again.
Here is a property that current exists but would like to be hidden/shown on toggle.
/// <summary>ModalStyle property for control</summary>
[XmlAttribute]
[DefaultValue(Utility.Common.Enumerations.ModalStyle.None)]
[Category(PropertyCategories.Rendering)]
[Description("Modal dialog style")]
public ModalStyle? ModalStyle
{
get { return control.ModalStyleActive; }
set { control.ModalStyle = value; }
}
My original though was to do some variant on #if DEBUG but use my own Conditional however I was unable to find a way to change my conditionals via button/toggle.
Can anyone please help with a solution to my problem? I have 20-30 controls with 20 to 30 properties that would like to be filtered.
I have two suggestions that, while they may not give you the exact functionality desired, will keep your solution much more straight forward.
First:
Since you are the library developer you should just decide what properties you want other developers to have access to though the IDE properties window. If a property is seldom used or not very useful through the IDE then just place the [Browsable(false)] attribute on it.
Second:
If you really want all properties to be visible in the IDE properties window, but want to give individuals a way of hiding the more advanced (or less used) ones, just throw them all in an 'Advanced' category. The user can then simply collapse that category and forget about them.
Also: Take a look at Oliver's answer to this question:
[how-to-show-or-hide-properties-dynamically-in-the-propertygrid]
I'm not sure to understand what you are trying to achieve.
When you use Attributes, those are static to the class. So, in your case, when you toggle a show/hide on an object, it's on an instance of the object. Also, you cannot change an attribute value at run-time.
Maybe you should try an alternate solution like creating a global
map<pair<type of object, property name>, is shown>
and update that accordingly from your editor.
And if you want to use something like a property grid, you will have a problem since it won't check your map, but it can be fixed. You could create a new class at run-time and make it a proxy to your current instance. (check on the net how to achieve that, but it's quite simple. There are 2 possibilities: compile from a string or use the ILGenerator.
Hope this help.
Maybe its something stupid, but I'm having a problem with a subclass of a DataGridView Control in VS2005 C#. I know I can subclass from almost anything by doing
public class MyDataGridView : DataGridView
{}
no problem, and I put in some things / elements I want applicable globally. Now, I take this gridview and put into a custom user control that will contain other controls too. So I have something like created by the visual designer. I grab some buttons, label, and my derived "MyDataGridView" on it.
public partial class MyCompoundDGVPlus : UserControl
So, now, I can visually draw, move, change all sorts of settings as needed, no problem.
Now, I want this "MyCompoundDGVPlus" class as the basis for other classes, of which I will manipulate settings specific, but want all to have the same look / feel, and otherwise similar flow, hence the derivations.
I've even set the "modifiers" setting to public, so I SHOULD be able to modify any of the properties of the controls at any derived level. So, now, I create a new subclass of "MyFirstDetailedDGVPlus" derived from "MyCompoundDGVPlus". Ok visually, all the label, button, datagridview appear. However, now I want to specifically define the columns of the datagridview here in this class visually, but its locked. However, the LABEL on the form, I CAN get all the property settings....
What am I missing.
Maybe you should take a look at this post as it seems to do what you are looking for :
DataGridView locked on a inherited UserControl
I have a custom collection, lets says COL, that derives from ObjectModel.Collection.
I have my own collection editor that works fine when a property, of type COL, is Read and Write enabled.
However, if I change the property to ReadOnly, the open editor button stops showing in the property grid.
As a test, I override my custom editor with the CollectionEditor, and that worked fine.
So, my question is, what check is the property grid making, that CollectionEditor passes but my collection editor fails?
There's not much to override in UITypeEditor, so I fear there's some hard coding going on with regards to CollectionEditor.
Cheers.
ETA:
I've answered the question below.
I've found out why it wasn't appearing and it appears to be a bug in the PropertyGrid.
The button does appear if the EditStyle is set to Modal, but does not appear if it's set to DropDown.
One would have thought that the styles were just for ..., well, style?
Looking in reflector, the issue occurs because additional checks of readonly propertyies (such as checking if it's a reference type - and enabling the button) only happen if the style is set to modal. Hmmm, nice one.
I think the behavior you describe in your own answer is not a bug and is by design, and frankly it's quite logical. Look the dropdown editors around: they offer the user to make a selection and therefore the result is a new value for the property (see ColorEditor, AnchorEditor, DockEditor, CursorEditor, ...). As such the property must not be readonly. A modal editor is more to edit a value (usually a reference type) and therefore can be used even if the property is readonly. Of course, this one can also be used to select a new value (like the FileNameEditor for example).
So maybe the answer is "look at your UI design". Are you sure you should use a dropdown editor to edit the content of a reference type?
I've come across the feature in Visual studio to auto-generate a subclass of a custom control using Add New Inherited User Control.
But I haven't found a clear description on how to e.g create a subclass of Button for instance. Apart from the actual way to do it, I'm also interested if VS provides helpful code-generation for this?
You just create your own class that inherits the Control, that you would like to subclass. For instance:
class BetterButton : Button { ...}
That is the easy part. Now you have the option to override various methods or properties, depending on what you want to achieve with your new Control. It could be anything, really. One thing I often see used is overriding OnPaint to get the control drawn in a custom way; and still getting the behaviour of the original control.
In terms of UserControls, I often see that a "parent" UserControl contains some UI logic and basic UI elements, while the subclassed controls are refinements of the parent for specific use.