Answered by:
Property Grid Extensibility - Filter TypePresenter

Question
-
Hi
I would like to open TypePresenter in a way that it display types which are derived from a specific types. There
Option - 1) How to set Filter property of existing TypePropertyValueEditor with my custom filter
Using EditorOptionAttribute i can provides values for AllowNull and BrowseTypeDirectly properties using following way. But how to pass Filter property as its expecting function / delegate of type Func<Type, bool>
[EditorOption(Name = "BrowseTypeDirectly", Value = "True")] [EditorOption(Name = "AllowNull", Value = "False")] [EditorOption(Name = "Filter", Value = "BaseTypeFilter")] public Type CustomType { get; set; }
OR
Option - 2) I have created a custom property value editor "CustomBaseTypePropertyEditor" as mentioned below.
public class CustomBaseTypePropertyEditor : PropertyValueEditor { public CustomTypePropertyEditor() { BrowseTypeDirectly = true; AllowNull = false; Filter = BaseTypeFilter; base.InlineEditorTemplate = new DataTemplate(); FrameworkElementFactory stack = new FrameworkElementFactory(typeof(StackPanel)); stack.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); FrameworkElementFactory typePresenter = new FrameworkElementFactory(typeof(TypePresenter)); Binding typePresenterBinding = new Binding("Value"); typePresenterBinding.Mode = BindingMode.TwoWay; typePresenter.SetValue(TypePresenter.TypeProperty, typePresenterBinding); typePresenter.SetValue(TypePresenter.BrowseTypeDirectlyProperty, BrowseTypeDirectly); typePresenter.SetValue(TypePresenter.AllowNullProperty, AllowNull); typePresenter.SetValue(TypePresenter.FilterProperty, Filter); stack.AppendChild(typePresenter); this.InlineEditorTemplate.VisualTree = stack; } public bool BrowseTypeDirectly { get; set; } public bool AllowNull { get; set; } public Func<Type, bool> Filter { get; set; } public Boolean BaseTypeFilter(Type typeToValidate) { if (typeToValidate == null) { return false; } if (typeof(MyBaseClass).IsAssignableFrom(typeToValidate)) { return true; } return false; } }
Custom activity will have following code
[Editor(typeof(CustomBaseTypePropertyEditor), typeof(PropertyValueEditor))] public Type CustomType { get; set; }
Problem here was, it filters only default types (Int, Bool, string, Array) which displays in combobox. Browse dialog is opened empty although there are classes which inherits from our base class
Looking forward to your support.
Regards
ProgrammerX
- Edited by ProgrammerX Thursday, August 16, 2012 9:55 AM
Thursday, August 16, 2012 6:55 AM
Answers
-
Continuing in the Option 2 vein, which I guessed I could get working,
Binding contextBinding = new Binding { Converter = new PropertyEntryToEditingContextConverter() }; typePresenter.SetValue(TypePresenter.ContextProperty, contextBinding); public class PropertyEntryToEditingContextConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { PropertyEntry parentProperty = value as PropertyEntry; if (parentProperty == null) { PropertyValue value2 = value as PropertyValue; if (value2 != null) { parentProperty = value2.ParentProperty; } } var parentModelItem = new ModelPropertyEntryToOwnerActivityConverter().Convert( parentProperty, typeof(ModelItem), null, null); return ((ModelItem)parentModelItem).GetEditingContext(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
The missing link was tying the type presenter back to an editing context so that it can figure out what the referenced assemblies are.
Tim- Proposed as answer by Tim Lovell-Smith Thursday, August 16, 2012 8:27 PM
- Marked as answer by Tim Lovell-Smith Monday, August 20, 2012 4:19 PM
Thursday, August 16, 2012 8:26 PM -
Also it looks like approach #1 can work - if you are using AttributeTableBuilder etc. to create the attribute in IRegisterMetadata. Then you can set a filter object at runtime without running into the constraints of declarative attributes.
Tim- Marked as answer by Tim Lovell-Smith Monday, August 20, 2012 4:19 PM
Thursday, August 16, 2012 8:31 PM
All replies
-
Continuing in the Option 2 vein, which I guessed I could get working,
Binding contextBinding = new Binding { Converter = new PropertyEntryToEditingContextConverter() }; typePresenter.SetValue(TypePresenter.ContextProperty, contextBinding); public class PropertyEntryToEditingContextConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { PropertyEntry parentProperty = value as PropertyEntry; if (parentProperty == null) { PropertyValue value2 = value as PropertyValue; if (value2 != null) { parentProperty = value2.ParentProperty; } } var parentModelItem = new ModelPropertyEntryToOwnerActivityConverter().Convert( parentProperty, typeof(ModelItem), null, null); return ((ModelItem)parentModelItem).GetEditingContext(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
The missing link was tying the type presenter back to an editing context so that it can figure out what the referenced assemblies are.
Tim- Proposed as answer by Tim Lovell-Smith Thursday, August 16, 2012 8:27 PM
- Marked as answer by Tim Lovell-Smith Monday, August 20, 2012 4:19 PM
Thursday, August 16, 2012 8:26 PM -
Also it looks like approach #1 can work - if you are using AttributeTableBuilder etc. to create the attribute in IRegisterMetadata. Then you can set a filter object at runtime without running into the constraints of declarative attributes.
Tim- Marked as answer by Tim Lovell-Smith Monday, August 20, 2012 4:19 PM
Thursday, August 16, 2012 8:31 PM -
Thanks for both the solution.
I make it working using IRegisterMetadata and assigning Filter property there.
Regards
ProgrammerX
Friday, August 17, 2012 1:42 PM