AttachedProperty and TypeConverter - xamarin.forms

I would like to use a TypeConverter defined by Xamarin Forms/MAUI: ColumnDefinitionCollectionTypeConverter that allows a specific format input to define columns on a Grid.
My problem is that I want to apply it on an AttachedProperty.
Usually, it is defined on properties (Bindable Properties, ...)
I tried to apply it on the Setter part but it doesn't work:
public static readonly BindableProperty ColumnDefinitionsProperty = BindableProperty.CreateAttached(
"ColumnDefinitions", typeof(ColumnDefinitionCollection), typeof(PH), default(ColumnDefinitionCollection),
propertyChanged: ColumnDefinitionsChanged);
[TypeConverter(typeof(ColumnDefinitionCollectionTypeConverter))]
public static void SetColumnDefinitions(BindableObject element, ColumnDefinitionCollection value) =>
element.SetValue(ColumnDefinitionsProperty, value);
public static ColumnDefinitionCollection GetColumnDefinitions(BindableObject element) =>
(ColumnDefinitionCollection)element.GetValue(ColumnDefinitionsProperty);
Any solution ?

It is unclear if you want to define your ColumnDefinitions and do something else with it; or if you want to have an input that is not ColumnDefinitions to them define them.
In both cases, I'd suggest using the bindable properties OnChanged Events that you seem to already have defined instead of TypeConverter.
If you want to define your ColumnDefinitions and use that information to affect other fields, you can simply define a your ColumnDefinitionsChanged method as
static void ColumnDefinitionsChanged (BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
}
I seem to understand thought that you want to give a different type of input to your control that would then dictate your ColumnDefinitions. If that's the case you can contrarywise define a new custome BindableProperty "ColumnTypeProperty" let's call it, that could be the type of a custom enum of yours and change your ColumnDefinitions values pragmatically from within this new property's ColumnTypePropertyChanged event.

Related

How do I bind to an Event that has a delegate using Caliburn.Micro?

Usually I can bind to an event like so:
cal:Message.Attach="[Event DragStarting] = [Action OnDragStarting($source,$eventArgs)]"
That is when an event has a signature like so:
public event EventHandler<DragDropCancelEventArgs> DragStarting;
How do I Attach to an event that has a delegate like the following:
public event CanDropEventHandler IDropTargetCanDropElement;
public delegate bool CanDropEventHandler(object sender, DropEventArgs e);
Any help figuring this out would be greatly appreciated!.
Thanks,
S
Why this isn't possible right away ?
Because Caliburn.Micro uses the Blend SDK's interactivity features to convert the syntax ([Event DragStarting] = [Action OnDragStarting($source,$eventArgs)]) to an EventTrigger and the EventTrigger class can't work with events that return a value, and if you think about it is logical, what to do with that return value. In general it is a bad practice for events to return values and you rarely come across such events.
How to fix this ?
The easiest solution would be to change the delegate signature if you could to look like this:
public delegate void CanDropEventHandler(object sender, DropEventArgs eventArgs);
Then you convert that bool value returned to a public property on the DropEventArgs class, after that Caliburn.Micro syntax will work correctly.
What if you can't change the delegate's signature ?
Then you will have to create an Adapter by deriving from the type that owns that event or by wrapping that type if it is sealed and then declare a new event with the signature i showed you above, and then listen to the new event.
Is there any other way ?
Maybe you can create a custom event trigger that derives from TriggerBase<T> which can work with events that have return values but this is an advanced technique that is a bit hard to implement, and anyway you won't to able to use CM's syntax anymore.
Edit: What i mean by that make the DropEventArgs class have that property instead of returning it from the delegate, so the DropEventArgs becomes something like this:
class DropEventArgs : EventArgs {
public bool CanDrop {get; set;} // OR CHOOSE WHATEVER NAME YOU WANT
}
and the delegate becomes like i showed you above.

Flex ItemRenderers

I know an ItemRenderer is a ClassFactory and that you can use the newInstance method of ClassFactory to get an instance of the ItemRenderer. My question, however, is is it possible to use methods of the ItemRenderer without using ClassFactory.newInstance()?
In my case I can't use this newInstance method because it doesn't keep the state.
Is there any way I can do this? Thanks!
An ItemRenderer is a component, like any other. The itemRenderer property of a list based class has a value of a ClassFactory. If you have a reference to an instance of the itemRenderer component, you can call methods on it.
You cannot call a method on any component if an instance if that component instance has not been created yet. So to call a method on an itemRenderer without using ClassFactory.newInstance() you must manually create your own instance using the new keyword.
You might want to implement the ItemRenderer as smart as it is needed to recreate the state depending in the data being set. On the other hand, make sure that the data contains everything needed. You barely want to interact with the renderers in a different scope then the renderer itself.
If it should necessary, a DataGroup dispatches a RendererExistence event when a renderer is added.
private function newList():List {
const list:List = new List();
list.addEventListener(FlexEvent.INITIALIZE, list_initializeHandler);
return list;
}
private function list_initializeHandler(event:FlexEvent):void {
const listBase:ListBase = ListBase(event.target),
dataGroup:DataGroup = listBase.dataGroup;
dataGroup.addEventListener(RendererExistenceEvent.RENDERER_ADD, dataGroup_rendererAddHandler);
dataGroup.addEventListener(RendererExistenceEvent.RENDERER_REMOVE, dataGroup_rendererRemoveHandler);
}
private function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void {
// renderer added
}
private function dataGroup_rendererRemoveHandler(event:RendererExistenceEvent):void {
// renderer removed
}
This is the way to go if you need to reference single item renderer instances.
Do you mean static functions and variables?
If you define a function (or variable, or const) as static, it is accessible via the class name, so you could define
class MyClass {
public static const className:String="MyClass.className (const)";
public static function getClassName():String {
return "MyClass.getClassName (function)";
}
}
trace(MyClass.className); //prints "MyClass.className (const)"
trace(MyClass.getClassName()); //prints MyClass.getClassName (function)

swt/jface databinding: PojoProperties vs PojoObservable

I'm writing a JFace dialog, and I'd like to use databing to a model object.
Looking at code I can see that there are times when I find a PojoProperties used to build the binding, while other time it is used a PojoObservables.
Looking at the Javadoc I can read:
PojoObservables: A factory for creating observable objects for POJOs (plain old java objects) that conform to idea of an object with getters and setters but does not provide property change events on change.
PojoProperties: A factory for creating properties for POJOs (plain old Java objects) that conform to idea of an object with getters and setters but does not provide property change events on change.
The same question applies to the difference that exists between BeansObservables and BeansProperties
The (obvious) difference sems to be that the observable allows to observe objects and the properties allows to observe properties, but since a Pojo has a getter and a setter for its data, what is the difference between them? And which of them should I choose for my dialog?
Here follows a code excerpt:
The POJO:
public class DataObject {
private String m_value;
public String getValue() {
return m_value;
}
public void setValue(String i_value) {
m_value = i_value;
}
}
The DIALOG (relevant part):
#Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
m_combo = new Combo(container, SWT.BORDER);
m_comboViewer = new ComboViewer(container, SWT.NONE);
}
The BINDING (relevant part):
// using PojoObservable
IObservableValue observeValue = PojoObservables.observeValue(m_dataObject, "value");
IObservableValue observeWidget = SWTObservables.observeSelection(m_combo);
// using PojoProperties
IObservableValue observeValue = PojoProperties.value("value").observe(m_dataObject);
IObservableValue observeWidget = ViewerProperties.singleSelection().observe(m_comboViewer);
I understand that one time I'm using a combo and another I'm using a ComboViewer, but I can get the combo from the viewer and bind the other way if I need...
Also, can I mix the two, for example use the observeValue with the ViewerProperties?
IObservableValue observeValue = PojoObservables.observeValue(m_dataObject, "value");
IObservableValue observeWidget = ViewerProperties.singleSelection().observe(m_comboViewer);
I am playing around a little with JFace viewers (especially ComboViewer) & databinding and discovered that if I use
SWTObservables.observeSelection(comboViewer.getCombo());
then databinding is not working correctly.
However, if I use
ViewersObservables.observeSingleSelection(comboViewer);
Then everything is working as expected.
Maybe this is a special for my case, so to get it a better overview I'll describe my set up in following paragraph.
I have modelObject with field named selectedEntity and entities and bind this ComboViewer to the modelObject.
I want to display all "entities" in model object, if I add any entity to the modelObject.entities collection then I want to this entity be added to combo automatically.
If user selects some item in combo I want to modelObject.selectedEntity be set automatically.
If I set modelObject.selectedEntity I want to combo selection be set automatically.
Source code can be found at: https://gist.github.com/3938502
Since Eclipse Mars, PojoObservables is deprecated in favor of PojoProperties and BeansObservables is deprecated in favor of BeanProperties so the answer to which one should be used has now become evident.

looping through object property names in actionscript

I have a dynamic class that I have created
public dynamic class SiteZoneFileUploadVO
{
public var destination:String = "sitezone";
public var siteZoneId:uint;
public var fileType:String;
public var fileContents:String;
public function SiteZoneFileUploadVO()
{
}
}
when I try to iterate over this object's property names it only iterates the dynamically added properties.
parameters.dynVar= "value";
for(var name:String in parameters)
{
trace(name);
}
Even though the object has all the properties equal to a value (ive checked this in the debugger) the only property name that will be traced is dynVar.
How can I iterate over all the property names and not just the dynamically added ones?
You can use describeType() to get an XML with all methods and variables of your class and then filter out the properties you want to iterate over (e.g. all variables) and store them in an XMLList.
As the next step you would then iterate over the XMLList and use square bracket notation on your object to access the filtered properties by their names. However, you can only access public properties this way because describeType() won't look at private properties.
If you're running flex:
Looked at a few posts, ObjectUtil.toString was the most promising, then looked at the flex source code for it, it uses another method ObjectUtil.getClassInfo which is exactly what you need. If you just want property names:
ObjectUtil.getClassInfo(myClass).properties
returns an Array of QName objects, each has a localName property which will give you a string for each property name
Just use trace(ObjectUtil.toString(parameters)); That should give you your entire object.

Overridable Constant?

Maybe I should just make this a public member, but I keep thinking it should be a constant.
SCENARIO
I have forms I'm rendering into PDFs (using iTextSharp). In code, the forms themselves all inherit a base class (OrderForm). Within OrderForm, there are a list of constants that I use for measurements when aligning things for the PDF rendering, such as LEFT_MARGIN, etc. These constants are used in several functions to determine where things go.
All the forms are virtually identical as they are comprised of the same components (header, address boxes, items, etc). However, the layout of the forms differ slightly... on one form, the address box is an inch further to the right (to fit in the envelope window my employer uses).
ISSUE
Rather than create a slew of constants for each margin, padding, blah blah for each form in the base class, eg: PURCHASE_ORDER_LEFT_MARGIN, INVOICE_LEFT_MARGIN, etc, wouldn't it be better to create an overridable LEFT_MARGIN that can be set in the "inheritee" [sic] object? My reasoning is that it is a constant that will not change within that object, only form to form, yet the renderings in the base class will remain relative to whatever that constant is.
I know I could simply create a public member and set its value, but I'd like to know the right way to go about this.
Thanks.
Constants are implicitly static (Shared).
Use a Readonly Property instead, and then you can choose to override it whenever or wherever need be.
A quick example ....
Class BaseClass
' Assume this field is set with a value from somewhere else'
Private _leftmargin As Integer
Overridable Readonly Property LEFT_MARGIN As Integer
Get
Return _leftmargin
End Get
End Property
End Class
Class DerivedClass1
Inherits BaseClass
Overrides Readonly Property LEFT_MARGIN As Integer
Get
Return 5 'specialized case for this class'
End Get
End Property
End Class
Class DerivedClass2
Inherits BaseClass
'uses base class LEFT_MARGIN'
End Class
Constants are compiled as literal values. If you have this (C#) source code:
public static class MyStringTestClass
{
// Fields
public const string ConstString = "Const String";
public void TestMethod()
{
string sc = MyStringTestClass.ConstString;
SomeOtherFunction(sc);
}
}
then the compiler will produce this:
public static class MyStringTestClass
{
// I'm not 100% sure if this declaration is removed as well...
public const string ConstString = "Const String";
public void TestMethod()
{
// ...but I know for sure that it will be removed
// everywhere it's used - including other assemblies!
string sc = "Const String";
SomeOtherFunction(sc);
}
}
As you see, "ConstString" is completely GONE and it's literal value is inserted everywhere.
So use the VB.net equivalent of a ReadOnly Virtual Property (I think "virtual" is called "Overridable" in VB.net?) and override it.
What you want is a regular property ... Any value that changes is not a constant ... :)
What you can do is to use methods instead of constants. At the base class the method will return the value of the constant as it is now.
Inheriting class can provide a new value for the "constant" by overriding the corresponding method.

Resources