Support for .NET attributes in ABL

Posted by Lieven De Foor on 14-Apr-2016 04:37

Hi,

Is there any way to achieve the functionality of .NET attributes in ABL?

Example:

In C# you can write:

[Bindable(true)]
public int MyProperty { get; set; }

More complex constructs are possible too.

Is there any way to achieve this in ABL?

Posted by Laura Stern on 14-Apr-2016 07:00

No, there's no way to do that.  There are certain annotations (as we call them) that are recognized by PDSOE or during mobile development.  But the ABL itself does not support them.  So no, you cannot bind a BibdingSource to an ABL property.  Besides it is not just this attribute that makes that work.  Any Bindable property requires a a bunch of functionality under the covers that we do t have.

Posted by Laura Stern on 14-Apr-2016 08:30

Generally speaking, you shouldn't need Bindable for an ABL property.  In the property body itself, the code can pull its value directly from the buffer associated with an ABL query.  You need (or want) to go thru .NET (i.e. .NET BindingSource) to get information from an ABL table so that it can populate an ABL property.  

Posted by Laura Stern on 14-Apr-2016 08:12

What exactly are you trying to accomplish?  

Supporting annotations in the ABL is on the roadmap but I don't know what priority it has.  But "Bindable" is probably not one of the things we will ever implement.  I assume that's what you're really interested in at the moment since that's what you put in your example.

All Replies

Posted by Laura Stern on 14-Apr-2016 07:00

No, there's no way to do that.  There are certain annotations (as we call them) that are recognized by PDSOE or during mobile development.  But the ABL itself does not support them.  So no, you cannot bind a BibdingSource to an ABL property.  Besides it is not just this attribute that makes that work.  Any Bindable property requires a a bunch of functionality under the covers that we do t have.

Posted by Lieven De Foor on 14-Apr-2016 07:08

Hi Laura,

I've been reading a bit into the TypeDescriptor and CustomTypeDescriptor classes and it looks like it might be possible to do something at run-time using these...

See this comment on stackoverflow: stackoverflow.com/.../129369

Are there any plans to support .NET attributes for ABL hybrid classes?

Posted by Laura Stern on 14-Apr-2016 08:12

What exactly are you trying to accomplish?  

Supporting annotations in the ABL is on the roadmap but I don't know what priority it has.  But "Bindable" is probably not one of the things we will ever implement.  I assume that's what you're really interested in at the moment since that's what you put in your example.

Posted by Laura Stern on 14-Apr-2016 08:30

Generally speaking, you shouldn't need Bindable for an ABL property.  In the property body itself, the code can pull its value directly from the buffer associated with an ABL query.  You need (or want) to go thru .NET (i.e. .NET BindingSource) to get information from an ABL table so that it can populate an ABL property.  

Posted by Lieven De Foor on 14-Apr-2016 09:21

I was looking into multiple unrelated things, but they all had .NET attributes in common.

First one was to have an ABL custom control that has a bindable abl property.

Next was trying to create a custom control that itself can be used as control container from within the visual designer: www.codeproject.com/.../Designing-Nested-Controls

Posted by Laura Stern on 14-Apr-2016 09:26

The latter case came up via Ken McIntosh on another forum discussion. I spoke to him a couple of times but I still don't understand the problem there.  If you create an ABL class that inherits from a .NET UserControl, it CAN be used as a control container within Visual Designer.  So I don't understand what wasn't working.

Posted by Lieven De Foor on 14-Apr-2016 09:42

I want to create a control that is a UserControl. In the Visual designer I would then create a new form, take the derived UserControl from the toolbox and put it on the form. Then I want to put other controls (say a Button) into the UserControl.

This is not possible from the designer, but apparently it should be possible by adding some attributes/code mentioned in that codeproject.com link.

In my actual case I have a panel inside the UserControl, and want the controls (Button, TextBox...) to be dragged inside that panel.

Posted by Lieven De Foor on 14-Apr-2016 09:45

So a UserControl CAN'T be used as a control container when put onto another control/form.

It CAN however be used as control container while designing the UserControl itself

Posted by Laura Stern on 14-Apr-2016 10:01

So let's say (in VS .NET)  you have a UserControl with a button and a TextBox on it.  Then you plop that UserControl onto a Form and then add a grid to it.  Does that grid only exist in that instance of the UserControl that is on that particular form?  I don't quite see the benefit of this.  Is it just to get it to look right visually - e.g., with a box around the button, TextBox and grid?

In any case - this is a Visual Designer issue, not an ABL issue.  As I said, we do support certain attributes for Visual Designer.  You'd have to address this question to the tools team.

Posted by Simon L. Prinsloo on 14-Apr-2016 10:01

I guess he wants to do the same thing as I (and most likely many others) frequently dream about: Bind the properties of an object directly to the display.

I've created my own type descriptors in the past to bind class properties to the screen, but it is quite painful. I've also seen at least two other implementations which use serialized data that ship with the code do provide these descriptors.  In all cases you also see a custom dll, most likely because of the road block I describe below.

First of all, it is a lot of work. You have to implement your own type descriptor and your own type description provider, which you will need to register with .Net. You will also need custom property descriptors andnattribute descriptors as well. 

Further more, when the property in the ABL object changes, it must implement the IComponent and INotifyPropertyChanged interfaces from .Net, so it is no longer portable. I normally work around it by implementing a portable version to call an empty protected method, passing the property name, in the setter and then inherit on from there, purely to implement the .Net interfaces and to override the empty method with one that Publish the required .Net Event. Back then we were still on our own with serialization, but as that have no impact on the implementation of the .Net interfaces, that was not a problem. Of course serialization will now most likely move back to you, despite the improvements we got in 11.6, as the derived type with the UI support is not the same as the portable base type.

At one point in the process you will hit a roadblock: When .Net tries to update the bound property. I cannot quite remember the details, but it had to do with the following method in System.ComponentModel.PropertyDescriptor:

public void SetValue(object component, object value)

Initially it seems that you simply need to inherit that object and overided the method with this:

DYNAMIC-PROPERTY(component,THIS-OBJECT:Name) = value.

Where THIS-OBJECT:Name is the name of the ABL property represented by this type descriptor. Of course, you will have to check the type of your property and UNBOX() value if it is a native type.

I can't remember exactly what went wrong here, but it had something to do with the Value-Types. What I do remember is that I figured out, from the stack traces generated in the error object, that there was a back and forth boxing and unboxing when Value passed through the bridge and it ended up crashing at the point where the CLRBridge it tried to invoke the on the OpenEdge side of the property descriptor.

I eventually resolved it by creating an abstract  C# class, inheriting from the System.ComponentModel.PropertyDescriptor, to serve as the base for the OpenEdge based property descriptor in order to be able to pass proper native types through the bridge.

Posted by Lieven De Foor on 14-Apr-2016 10:17

[quote user="Laura Stern"]

Then you plop that UserControl onto a Form and then add a grid to it.  Does that grid only exist in that instance of the UserControl that is on that particular form?

[/quote]

No, it doesn't even exist inside that UserControl. It only exists as control of the Form, and does not get inside the UserControl (it gets behind or on top of it, but not IN it)

You can move the UserControl around, but the grid does not move with it (which makes sense since it's not a child of the UserControl).

In Visual Studio you can achieve what I want as described in the codeproject link using Attributes.

So we get to the original question, how can I do this in ABL.

Not with attributes, since they don't exist, but perhaps at runtime by using a TypeDescriptor/CustomTypeDescriptor... or I should turn to c# to fabricate what I need and consume it in ABL...

[quote user="Laura Stern"]

 You'd have to address this question to the tools team.

[/quote]
How can I reach them?

Posted by Lieven De Foor on 14-Apr-2016 10:24

[quote user="Simon L. Prinsloo"]

I guess he wants to do the same thing as I (and most likely many others) frequently dream about: Bind the properties of an object directly to the display.

[/quote]

Exactly!

Now that I've read your comments I'm not sure whether to pursue my search or just give up and try to cook up something in C# instead...

Posted by Mike Fechner on 14-Apr-2016 10:30

Hi Lieven,
 
we are using the CustomTypeDescriptor in our framework and have also implemented an ABL Property that is data-bindable.
 
However you will also have to use a .NET Interface which enforces this property. Only ABL properties that are required for implementing .NET Interfaces become .NET-visible at runtime. So you will need at least a little bit of C# for data binding.
 
Mike

Posted by Laura Stern on 14-Apr-2016 10:52

Regarding the UserControl - just spoke to Ken McIntosh again.  I presume this is the same case, but it is a bit different than you described.  The customer wants a UserControl with some stuff in it.  Then other developers want to customize that in different ways.  So they create another ABL class that inherits from the original one (which already was an ABL class inheriting from a .Net UserControl).  But now - even without putting this new UserControl onto a form - the developer cannot add more controls to it in Visual Designer.  This makes much more sense to me.  But again - it is an issue for the Visual Designer folks.  Ken has already posted a question to the Tools forum (sorry, I don't know how to point you at that, but clearly he can).  He hasn't gotten a response yet.

Posted by Laura Stern on 14-Apr-2016 12:06

Regarding binding: Ah yes, I was thinking backwards.  So you want a .NET control that is bound to an ABL class property as opposed to being bound to a buffer or a query.  Correct? That was one of the possibilities for the ProBindingSource way back when.  But we didn't do it.

Interesting Mike.  So you don't need the ProBindingSource for this. You could just use a regular .NET BindingSource if you wanted to, right?  Just asking to make sure I understand what you're doing.

Posted by Mike Fechner on 14-Apr-2016 13:41

Hi Laura,

we do actually still need the ProBindingSource.

Situation is the following. We have a lookup control that works on a visible (human readable value) and a technical key (e.g. a GUID). When the user selects a value from the lookup table (let's say Item) both the Lookup's Text/Value (human readable) and LookupKeyValue (GUID) property get's assigned within the lookup (actually an extension to the UltraTextEditor). So the ProBindingSource takes care that the Item.ItemGuid field value, that the Lookup Control assigned to it's LookupKeyValue property get's assigned to the OrderLine.ItemGuid field.

It's the same as with binding a Field to a Control's Text/Value/Tag property with the only difference, that the property is ABL defined (and enforced by a .NET Interface, to become member of the .NET's view of the ABL Hybrid type).

This thread is closed