Hello,
I am using the RadPropertyGrid EditorAttribute to define the editor for a property. Currently, I only have the ability to pass the TargetProperty to my editor through this attribute. However, I would like to be able to pass some extra properties such as filters (not necessarily through binding).
My current code looks like this:
[Telerik.Windows.Controls.Data.PropertyGrid.Editor(typeof(MultipleTagsEditorPreview), "Value", Telerik.Windows.Controls.Data.PropertyGrid.EditorStyle.None)]
public ObservableCollection<
TagConfiguration
> Tags {get;set;} //Full block removed for brevity
What I would like to do is something like this:
[Telerik.Windows.Controls.Data.PropertyGrid.Editor(typeof(MultipleTagsEditorPreview), "Value", Telerik.Windows.Controls.Data.PropertyGrid.EditorStyle.None, "Filter1,Filter2,Filter3")]
public ObservableCollection<
TagConfiguration
> Tags { get;set;}
For obvious reasons, I can't create a new editor for every combination of filters. I think it might be easier to inherit the EditorAttribute class and override it to contain a Filters property and have my own constructor that calls the base constructor. But I am not sure how to pass my properties to the editor once it has been instantiated by the RadPropertyGrid. Is there some behavior that I can override to do this? For example:
MultipleTagsEditorPreview editor = Activator.CreateInstance(this.EditorType);
editor.Filters = this.Filters; //this is where I would pass the filters to my editor
return editor;
Any help would be appreciated,
Thanks
7 Answers, 1 is accepted
Why don't you try passing the DataContext and then handle the logic inside your custom control?
Generally, when you have the following definition:
[Telerik.Windows.Controls.Data.PropertyGrid.Editor(typeof(PhoneEditorControl)]
The DataContext of the editor will be the corresponding property. And if that property is a kind of a ViewModel and holds the information you need (the Filters), you will be able to bind the custom control as you need.
Regards,
Maya
Telerik
Because Maya,
Sometimes you just switch from one property grid to another, or already written a code and don't want to change your entire code for it.
Sometimes, and bound property is just a simple observable collection, or even a value type (like an int), and you don't want to create a view model just for it.
I'll give you an example: The opacity, width and height of elements in WPF are double. Microsoft does not wrap then with another class (because it is pointless), but however, you still see the Visual Studio property grid, and also in Blend property grid, that the Editor for these properties is a slider, whereas in the Opacity, it is limited for values 0 to 1 (or 0 to 100%)
I had the same problem. I have a custom slider that gets in the Ctor some properties like min, max etc. It was a UserControl, so I couldn't inherit just the code (assuming that the user control is located on another assembly). It that was working, I would also need to have like 7 sub classes for the custom slider, which each of them just passes a different min max etc.
This is off course, an absurd.
Activator.CreateInstance gets params in its ctor, so you could pass some arguments in the Editor attribute to be used.
However, this is not the best solution, since most controls don't have a ctor that accepts parameters (since it is meant to be used in Xaml).
For this reason (and due to the Editor limitation), I had to figure a solution.
I've made up with a custom attribute called PropertyValueAttribute:
[AttributeUsage(AttributeTargets.Property, AllowMultiple =
true
)]
public
class
PropertyValueAttribute : Attribute
{
string
_propertyName;
object
_value
;
public
PropertyValueAttribute(
string
propertyName,
object
value)
{
_propertyName = propertyName;
_value = value;
}
public
override
object
TypeId
{
get
{
return
this
;
}
}
public
string
PropertyName
{
get
{
return
_propertyName;
}
}
public
object
Value
{
get
{
return
_value;
}
}
}
Then, I put it above my property, for example:
[Display(Name =
"Opacity"
, GroupName =
"Properties of Appearance"
, Order = 500),
Telerik.Windows.Controls.Data.PropertyGrid.Editor(
typeof
(CustomSliderView),
"Value"
), PropertyValue(
"Minimum"
, 0), PropertyValue(
"Maximum"
, 100), PropertyValue(
"AdditionalChar"
,
"%"
)]
public
int
ElementOpacity
{
get
{
return
(
int
)(Opacity * 100);
}
set
{
Opacity = value / 100.0;
}
}
Then, when the actual editor is being created... Which is in the FieldLoaded Event, I apply my properties as follows:
private
void
propertyGrid_FieldLoaded(
object
sender, FieldEventArgs e)
{
var pd = e.Field.DataContext
as
PropertyDefinition;
// Prevent reflection if not needed
if
(pd !=
null
)
{
var desc = pd.SourceProperty.Descriptor
as
PropertyDescriptor;
for
(
int
i = 0; i < desc.Attributes.Count; i++)
{
var att = desc.Attributes[i];
if
(att
is
PropertyValueAttribute)
{
PropertyInfo propertyInfo = e.Field.Content.GetType().GetProperty((att
as
PropertyValueAttribute).PropertyName);
// make sure object has the property we are after
if
(propertyInfo !=
null
)
{
propertyInfo.SetValue(e.Field.Content, (att
as
PropertyValueAttribute).Value,
null
);
}
}
}
}
}
This off course doesn't work when you merge several objects into one (by selecting Union or Intersect, and passing an IEnumerable of objects), since in this case you ignore all attributes (including the editor), but this is a special scenario.
My suggestion was to create a wrapper object that will hold all the information from the custom attribute and everything else you need and to use that type for the property of the business object - so instead of being int ElementOpacity to be MyViewModel ElementOpacity. Then, when you work with the editor, you will be able to set the properties - like Maximum, Minimum, etc. to your custom editor. My presumption was that you will work with one custom editor for similar properties, i.e. slider for numeric properties.
Nevertheless, I am happy to see that you found a more appropriate solution for your scenario. Let us know in case we can be of any further assistance.
Regards,
Maya
Telerik
Hi Maya,
Actually, I'm not the original author of this thread. I just replied in order to suggest why wrapping the property with an object is not always a good solution, and to also offer the author a solution.
Thanks Maya and Benn for your answers! Maya, using the DataContext indeed works. Benn, your solution is very creative and useful for my particular scenario, especially since I don't have to create extra variables to bind to. Thanks a lot.
Hafsa
I am not absolutely sure of your setup but by default, the DataContext of the UserControl would be the property for which it is used as an editor. For example, in the Editor Attribute demo in our SDK Samples Application, the DataContext of the Custom Control(PhoneEditorControl) would be the object of type PhoneNumber, so you can bind to its relevant properties(CountryCode, Number, RegionCode). What are you trying to achieve at your end? Can you provide more details on your setup?
Regards,
Stefan Nenchev
Telerik by Progress