Programmatically filter custom properties - c#

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.

Related

Is Enum the only way to show values for a Property as drop down list in the design time

I know when I use Enum and put it as Property for class/UserControl, it will show/display it with drop down list like this:
But is this the only way to display available values like "drop down list"? Do we have other ways to do it?
Edit: The scope is Windows Form Application
For who didn't understand me
In that image(http://i.stack.imgur.com/NMank.png) where wrote "DataBase" is the Name of the Property in design time.
The values: NotChoseYET, ChooseDataBase, ThereAlreadyDataBase are values in Enum I created.
As you can see they displayed in a DropDownList in the design, so I want to ask if there are other ways to display like that without Enum?
Update
After tons of searches, I found what I had answered was only partially correct, so I would like to answer it again.
The answer to your question is a definite NO, we have some other way to show values on property as DropDownList. Like what I mentioned in my old answer, if values come from some kind of Set, or in other word it belongs to a collection of values, it will be displayed as a DropDownList without any extra efforts (because the UITypeEditor has been specified for them, you will understand this point later). Here are 3 examples:
If a Property is a bool, in the designer it will show you a DropDownList contains True and False;
If a Property is a Font.Name, in the designer it will show you a DropDownList with SmallIcon;
if a Property is a Color, in the designer it will show you some DropDownList encapsulated in a TabControl.
From those "native" examples, you may realize a fact: we could somehow use some controls other than a simple DropDownList in the Property Tab during the design time. For example, a Color property gives a TabControl instead of a simple DropDownList, and a Font.Name property gives a customized DropDownList.
Yes, this is the second thing I am going to talk about. You are not only able to customize the items in the DropDownList, but also the View of that Value Choosing Editor.
However, this is very tricky and non-trivial. You are not recommended to do this unless it really adds value to your user control in the design time.
In short, you need to inherit from UITypeEditor, and override 2 functions:
GetEditStyle(), which
indicates to the design environment which kind of user interface your UI type editor implements
and EditValue(), which
establishes the interaction between the design environment and the user interface for editing your custom type
Then for your property which makes use of the Editor, you need to add EditorAttribute to it to specify the Editor used when selecting value of that property.
For better details, you are suggested to check this MSDN walk-through, which explains how to design a customized Value Editor in the design time.
Now back to the point where we left over. The native type, like bool and Color, has already bond to
a UITypeEditor, thus no further working should be done.
Old Answer:
For properties, you need to choose a value from a kind of Set, and all elements in that Set will be displayed as Items in a DropDownList during design time. When you try to define the Set, Enum is one method to define them. Also, you can use set of struct, like Color. In other words, if you have a Property that returns Color (or other structs), during design time it will appear as a drop down list.
You can easily add items to a combobox control by using its .Items property:
private void TestForm_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
// add items to the combobox
// you can use any object. The .ToString() method will be used for displaying it
cbxTest.Items.Add("This is test string " + i);
}
}
This will yield the following form:
I came across this question as I recently needed to do the same.
I posted a question ... which in the end I anwsered myself here.
In a nutshell: Implement a type converter
GetStandardValuesSupported(ITypeDescriptorContext context) to return
true and GetStandardValues(ITypeDescriptorContext context) to return
the StandardValuesCollection for the property type. Finally just
decorate the property like so:
[TypeConverter(typeof(MyClassConverter))]
public MyClass MyProperty { get; set; }
The designer property window will now have a dropdown with valid values.

How do I collapse a Category attribute with System.ComponentModel?

I have a number of categories on my design time component that are being expanded by default.
I'd like to have them appear collapsed by default, or at least problematically collapse them before the user sees them.
[Category("Misc")]
public int Id
{
// ...
}
Do I need to use a type converter? The docs on this are pretty sketchy...
I don't think there's a viable way to do this. While you can programmatically collapse a category in a PropertyGrid control, you'd need to get access to the instance being used by Visual Studio (or whatever editor they're using). As far as I know there's no way to control that declaratively, e.g. with an attribute or anything.
It might be possible with a custom UITypeEditor or something, but it would be fragile and need an awful lot of effort, and personally this feels like the kind of thing that should be left to the users' preferences anyway.

Completely disable CollectionEditor

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.

C# How to implement a form which controls are dependant of some properties?

In my application, different controls are only used dependent of the values of properties from a particular object. The forms constructor accept this object as a parameter.
The form has always some basic functionality, no matter what properties are set of the particular object.
Now I have something like this:
if(myObject.SomeProperty)
{
myControl.Visible = true;
myOtherControl.Visible = false;
// and so on
}
At this time, the controls that are dependant of SomeProperty are buttons and tab items. However, I can imagine that in the future other controls are added to the form and are also dependant of SomeProperty.
As you might guess, I want to set this up the right way. But I don't know exactly how. How would you implement this?
There are multiple ways I can think of solving this, depending on your situation you could select the best suited to you.
1. Databinding is one elegant solution when managing the state (visibilit or other properties) of multiple control's depend on a different object. Additional details in this question
2. You could write different functions if the combination of the states is only limited to couple of cases to at most 4-5 cases. That ways you can still reason about the methods which set the state depending on the object you are depending on. Ex: Basic_Editing, Advaced_Editing, Custom_Editiong etc.
3. If the number of cases are limited you could create multiple forms (User controls) and load them on demand based on the state of the dependent property (or object you are talking about).
Just having a bunch of if else's makes your code harder to maintain, or comprehend, logically group the states so that 1. You could reason about it later, 2.Someone else understands the reason/logic 3.When there is a change required it can be localized to one of these modular methods (techniques) reducing the time to fix, and test.
I would do it like this in form constructor:
myControl.Visible = myObject.SomeProperty && !myObject.SomeOtherProperty;
myOtherControl.Visible = !myObject.SomeProperty;
....
Is it the less code and its rapidly changing.
OR
You can create separate functions that will generate controls dynamically at runtime for each form view based on object properties.
First i can see you are setting visibility on/off it means you have already controls on the form every time.. , so that not a good practice, instead create controls only when needed.
As for your scenario you can have an function like Initialize() which contains all the code for checking if showing a particular control should be shown or not and then create it and add it to Forms control collection. If any new control come to be added later you have one function to update.
A more precise answer can be given if you can provide more detail to you scenario

Programmatically hiding properties in a PropertyGrid

I'm looking to hide/show properties depending on what selection the user makes in a drop. I am handling the event fine, but cannot actually make the correct properties disappear. The solutions I have found on line are mainly from 2005 and as I've had very little experience with it I thought I must be doing something wrong if hiding properties is this hard.
So far I have tried accessing the property once the event is handled but the ReadOnly and IsBrowsable properties are read only.
The propertygrid has a property BrowsableAttributes that takes an Attribute list but only works negatively and cannot do or - only and. Providing an attribute collection of ; category - 'test' and isbrowsable - true; returns those that match both and as I can't provide multiple AttributeCollections I cannot make the search specific enough to hide the necessary ones whilst leaving others visible.
I have been banging my head against a wall for the past couple of hours thinking there must be an easier way.
Have you tried applying this attribute to a property:
[Browsable(false)]
public object SomeProperty{
}
In that way SomeProperty will not appear on the propertygrid.
To do what you want to do here, you'd need to implement ICustomTypeDescriptor on your class, which is what the PropertyGrid will use to query your class/object to find out what items to display in the PropertyGrid, how to edit them, what category/description they should have, etc.
It can get quite messy, but it seems that there's a pre-written set of helper classes for you on Code Project at http://www.codeproject.com/KB/grid/PropertyGridDynamicProp.aspx.
I'd started writing my own version of the code given at Code Project and after hitting a snag I did some googling and came up with the Code Project link. It looks like they've done a lot better than I was. I've downloaded the code and it seems to work quite well.
If it doesn't solve your problem, please let me know and I'll dig a bit deeper.

Categories

Resources