Reputation: 1809
I'm developing an Full-Text Index Aspect, and I got to the point where I can specify a property to be a full-text index.
However, the next thing I want to do is specifying inside the SQL Full Text Index syntax, the "TYPE COLUMN xx", where "xx" is another property of the same entity.
To that end, I would like to ask with the CodeFluent Aspects, how do I set it to provide a drop down list of all other persisted properties for current entity for an aspect input?
Here's the CodeFluent Aspect XML code I have so far:
static FullTextIndexing()
{
Descriptor = new XmlDocument();
Descriptor.LoadXml(
@"<cf:project xmlns:cf='http://www.softfluent.com/codefluent/2005/1' defaultNamespace='FullTextIndexing'>
<cf:pattern name='Full Text Indexing' namespaceUri='" + NamespaceUri + @"' preferredPrefix='ftind' step='Tables'>
<cf:message class='_doc'>CodeFluent Full Text Indexing Aspect</cf:message>
<cf:descriptor name='fullTextIndex'
typeName='boolean'
category='Full Text Index'
targets='Property'
defaultValue='false'
displayName='Full-Text Index'
description='Determines if property should be a full text index.' />
<cf:descriptor name='fullTextIndexTypeColumn'
typeName='text'
category='Full Text Index'
targets='Property'
displayName='Type Column'
description='The type column for the full text index.' />
</cf:pattern>
</cf:project>");
}
This gives me a "text box". What I want is a drop down of the other properties of the same entity.
I tried to use the UITypeEditor to make a dropdown, but it doesn't seem to be working. The "Type Column" is greyed out, and it has a black box.
I might be doing something wrong.
My custom UITypeEditor class is as follows:
namespace CodeFluent.Aspects.AspectEditors
{
public class OtherPropertyDropDownEditor : UITypeEditor
{
private IWindowsFormsEditorService _editorService;
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
// drop down mode (we'll host a listbox in the drop down)
return UITypeEditorEditStyle.DropDown;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
// use a list box
ListBox lb = new ListBox();
lb.SelectionMode = SelectionMode.One;
lb.SelectedValueChanged += delegate
{
// close the drop down as soon as something is clicked
_editorService.CloseDropDown();
};
// use the Property.Name property for list box display
lb.DisplayMember = "Name";
// this is how we get the list of possible properties
IEnumerable<Property> otherProperties = GetOtherPersistentProperties(context);
foreach (Property otherProperty in otherProperties)
{
int index = lb.Items.Add(otherProperty);
if (otherProperty.Equals(value))
{
lb.SelectedIndex = index;
}
}
// show this model stuff
_editorService.DropDownControl(lb);
if (lb.SelectedItem == null) // no selection, return the passed-in value as is
return value;
return lb.SelectedItem;
}
private IEnumerable<Property> GetOtherPersistentProperties(ITypeDescriptorContext context)
{
// context is of type ITypeDescriptorContext, got from EditValue overloads.
var property = TypeNameEditor.GetObject<Property>(context);
IEnumerable<Property> otherEntityProperties = null;
if (property != null && property.Entity != null)
otherEntityProperties = property.Entity.Properties.Where(p => p.IsPersistent && p != property);
return otherEntityProperties;
}
}
}
The XML I have so far is this. Notice I added the "editorTypeName".
static FullTextIndexing()
{
Descriptor = new XmlDocument();
Descriptor.LoadXml(
@"<cf:project xmlns:cf='http://www.softfluent.com/codefluent/2005/1' defaultNamespace='FullTextIndexing'>
<cf:pattern name='Full Text Indexing' namespaceUri='" + NamespaceUri + @"' preferredPrefix='ftind' step='Tables'>
<cf:message class='_doc'>CodeFluent Full Text Indexing Aspect</cf:message>
<cf:descriptor name='fullTextIndex'
typeName='boolean'
category='Full Text Index'
targets='Property'
defaultValue='false'
displayName='Full-Text Index'
description='Determines if property should be a full text index.' />
<cf:descriptor name='fullTextIndexTypeColumn'
category='Full Text Index'
targets='Property'
editorTypeName='CodeFluent.Aspects.AspectEditors.OtherPropertyDropDownEditor, CodeFluent.Aspects.AspectEditors.OtherPropertyDropDownEditor, CodeFluent.Aspects.AspectEditors'
displayName='Type Column'
description='The type column for the full text index.'
/>
</cf:pattern>
</cf:project>");
}
Upvotes: 3
Views: 90
Reputation: 139187
What you can do is add an xml attribute to your descriptor to define a custom TypeConverter type name, for example:
<cf:descriptor name='fullTextIndexTypeColumn'
typeName='text'
category='Full Text Index'
targets='Property'
displayName='Type Column'
description='The type column for the full text index.'
typeConverterTypeName='ClassLibrary1.MyAspectConverter, ClassLibrary1'
/>
Then you need to implement the MyAspectConverter class (here in a ClassLibrary1.dll), for example like this:
public class MyAspectConverter : StringConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var list = new List<string>();
var property = TypeNameEditor.GetObject<Property>(context);
if (property != null && property.Entity != null)
{
list.AddRange(property.Entity.Properties.Where(p => p.IsPersistent).Select(p => p.Name));
}
return new StandardValuesCollection(list);
}
}
ClassLibrary1 needs to reference CodeFluent.Runtime.dll
, CodeFluent.Model.Common.dll
and CodeFluent.Model.dll
(in general from C:\Program Files (x86)\SoftFluent\CodeFluent\Modeler
).
You will need to copy the ClassLibrary1.dll
that contains this converter to Visual Studio where the IDE can load it from, for example in C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE
for Visual Studio 2015.
Note if you define your aspect in code, you can put this converter class in the same DLL, but you'll always need to copy it in Visual Studio directory.
Restart Visual Studio, and you should see something like this in the Visual Studio property grid:
As stated in the comments, you can also create a UITypeEditor using the same principle, if you need more advanced editing (and use the 'editorTypeName
' XML attribute instead of the 'typeConverterTypeName
' attribute), but it's not needed for a list of strings.
Upvotes: 1