My question is very similar to QML Access object property by property name string except I would like to access a root property...
I would like to be able to do that:
Rectangle {
property string color1: "blue"
property string color2: "red"
property string curColor : "color1"
color: /*something like*/ currentScope[curColor]
}
Note : this is a MWE, I know there are much smarter way of doing it in this case. My use case is to provide a simple to use Adapter that needs to know on which property it must act. I know about Binding, but it requires and id... I would like to avoid using an explicit id and work in the current scope.
You just need to give your Rectangle an id so you can reference it.
Rectangle {
id: root
property string color1: "blue"
property string color2: "red"
property string curColor : "color1"
color: root[curColor]
}
UPDATE:
To do it without an id, you can use the this pointer. It is in the documentation, but not easy to find.
Rectangle {
property string color1: "blue"
property string color2: "red"
property string curColor : "color1"
color: this[curColor]
}
Related
I have created new custom control in Xamarin.Forms which is derived from View and used FontSize property customize the custom control text. I will provide Large, Small Medium type in FontSize. So, FontSizeConverter attribute added above the FontSize property. in my custom control.
[C#]:
public class CustomControl : View, IParentThemeElement
{
[TypeConverter(typeof(FontSizeConverter))]
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { this.SetValue(FontSizeProperty, value); }
}
public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
"FontSize", typeof(double), typeof(CustomControl), GetDefaultTextFontSize(), BindingMode.Default, null, OnFontSizePropertyChanged);
}
Then FontSize given in string as you see in the below sample code in my custom control and it is working fine. But i am getting warning message in Xml code like "invalid value for property 'FontSize': 'Large'.
[XAML]:
<edit:CustomControl HeightRequest="100" FontSize="Large" x:Name="editor">
I referred Xamarin.Forms Entry FontSize. They used the same code. But in Entry, I not found any warnings. Anyone please help to resolve the warning.
Thanks,
I'm trying to get the "Name" of VCard properties, but I don't see a
"getName()" function. However, the following seems to work. Is it
legitimate to rely upon?
for (VCardProperty property : vCardThis.getProperties()){
String propKeyS = property.toString() ;
int atLoc = propKeyS.indexOf("#") ;
String propName = propKeyS.substring(0, atLoc) ;
System.out.println(propName) ;
}
The name that is assigned to the property when it is serialized is stored in the property's scribe class.
To get a property's scribe class, use the ScribeIndex class like so:
ScribeIndex index = new ScribeIndex();
for (VCardProperty property : vCardThis.getProperties()){
VCardPropertyScribe<? extends VCardProperty> scribe = index.getPropertyScribe(property);
System.out.println(scribe.getPropertyName());
}
I had an idea to use custom attributes on the properties in a class for databinding purposes in a winforms interface. For example, setting and changing the backcolor, forecolor, and tooltip on a textbox with invalid data. I find that I can bind up the control properties of txtTest for backcolor, etc., to a custom attribute such as BackColorAttr decorating a property in the class such as Name, with no problem. The property value itself is bound to the Text of the textbox, two-way binding of that works just fine, and the initial backcolor, forecolor, etc., are set from the initial values of the custom attributes just the way I had hoped. I'm doing all this through a BindingHelper class that reduces all the coding to a couple of generic methods.
Where I'm stumped is manipulating the values of the custom attributes at a later time. Changing the backcolor to red, for example. Nothing I've tried seems to work. Has anybody tried something like this, or have some guidance as to how I might proceed?
I dont quite follow the first part or what binding has to do with colors or Attributes, but thats not how Attributes work. They are not Property wrappers and Properties, Methods and Types have no idea of the Attributes associated with them (and vice-versa). They are meta data compiled into the assembly. As such, you cant change the value in any meaningful way.
Test class and test Attribute:
Public Class BarState
Inherits Attribute
Public Property State As String
Public Sub New(t As String)
State = t
End Sub
End Class
Public Class Foo
<BarState("red")>
Public Property Name As String
End Class
Since State is a property, test if we can set it:
Dim f As New Foo
' get props for the Type
Dim pi As PropertyInfo = f.GetType.GetProperty("Name")
Dim attr = pi.GetCustomAttributes(GetType(BarState), False)
If attr.Length > 0 Then
' get prop info for the State property on the Attr Type
Dim pa As PropertyInfo = attr(0).GetType.GetProperty("State")
' change it
CType(attr(0), BarState).State = "GREEN"
' or
'pa.SetValue(attr(0), "GREEN", Nothing)
' print it (prints "GREEN" but it does not persist)
Console.WriteLine(CType(attr(0), BarState).State)
End If
'get the attr again as you might do next time thru
attr = pi.GetCustomAttributes(GetType(BarState), False)
' print the value (Print "red")
Console.WriteLine(CType(attr(0), BarState).State)
The first print will be "GREEN" but that is only for this instance - it does not persist. The next time you get it, it reverts to "red". Since an Attribute is a Type, we can try to Reflection to change the value using pa.SetValue(attr(0), "GREEN", Nothing) which is commented out. It still wont persist because "red" is compiled into the assembly which is what your starting point will always be.
It might seem like you could keep a Dictionary or collection of the attribute instances for all the properties on all the types. That could work except, they all look alike, so you would have to create a hash to track which Attribute instance goes with what Property on what Type.
And you'd have to keep that collection in sync with the underlying instance objects. The Attribute instance wont know the instance it came from is gone and so the state setting should revert, so your Attribute manager would need to handle that.
You might look into "weavers" which use attributes to tag things (like a value range) then rewrite the assembly to weave in range checks for the tagged properties. Sort of sounds like what you are after I dont know what else they might do along the lines of what you describe.
I'm trying to deserialize two types of json:
{
name: "bob",
worksAt: {
name: "Bobs department store",
location: "downtown"
},
age: 46
}
and
{
name: "Tom",
worksAt: "company:Bobs department store",
age: 27
}
into these objects:
The first way creates two new objects, the second way requests the object from the database based on the contents of a string.
sort of like how jackson mapper can deserialize an arbitrary string into an object, for objects like this:
public class Company{
public String name;
public Employee[] employees
public Company(){}
public Company(String json){
//turn string into object using whatever encoding you want blah blah blah...
}
}
The trouble is I need both. I need it to handle objects and strings. Both could arrive from the same input.
The first think I tried was making a Converter
It says these create a delegate type to pass to the deserializer, but the converter is always applied even when the datatype isn't a string. So that didn't work.
I've also tried a normal deserializer, but I can't find a way to defer to the BeanDeserializer. The beanDeserializer is so complicated that I can't manually instantiate it. I also see no way to defer to a default deserializer in jackson mapper.
Do I have to re-implement jackson mappers deserialization to do this? Is there any way for a deserializer to say "I can't do this, use the default implementation."?
Edit: Some further progress. Based on the Jackson Mapper source code, it looks like you can instatiate bean deserializers like this:
DeserializationConfig config = ctxt.getConfig();
JavaType type = config.constructType(_valueClass);
BeanDescription introspect = config.introspect(type);
JsonDeserializer<Object> beanDeserializer = ctxt.getFactory().createBeanDeserializer(ctxt, type , introspect);
but for some reason all the _beanProperties have the FailingDeserializer set for their _valueDeserializer and the whole thing fails. So I have no idea why that happens...
Have you tried writing a custom deserializer? This gives you the most control on how Jackson deserializes the object. You may be able to try to deserialize one way, and if there's an error, try another way.
Jackson can also handle polymorphic deserialization, though this would require a small change to the json to include type information, and it sounds like your problem constraints might not allow that.
If I understand the problem correctly, I would recommend using JsonNode. You can define a setter in your top-level type like this:
setWorksAt(JsonNode node) {
if (node.getNodeType == JsonNodeType.STRING) {
String name = node.getText();
name = name.substring(name.lastIndexOf(':'));
this.company = new Company(name);
} else if (node.getNodeType == JsonNodeType.OBJECT) {
this.company = mapper.treeToValue(node, Company.class);
}
}
That allows you to handle the two separate worksFor inputs, while still allowing the standard mapper to handle any substructures for the OBJECT case.
With recent versions of Jackson (2.8+ I think, definitely works with 2.9) you can use multiple #JsonCreator and do something like this:
public class Company {
private String name;
private String location;
private Company(String name, String location) {
this.name = name;
this.location = location;
}
private Company(String stringRepresentation) {
// add code here to parse string and extract name and location
}
#JsonCreator
private static Company fromJson(
#JsonProperty("name") String name,
#JsonProperty("location") String location)
{
return new Company(name, location);
}
#JsonCreator
private static Company fromJson(String str) {
return Company(str);
}
}
I have a control with a inner TextBox. I want to make a direct relationship between the Text property of the UserControl and the Text property of the TextBox. The first thing I realized is that Text was not being displayed in the Properties of the UserControl. Then I added the Browsable(true) attribute.
[Browsable(true)]
public override string Text
{
get
{
return m_textBox.Text;
}
set
{
m_textBox.Text = value;
}
}
Now, the text will be shown for a while, but then is deleted. This is because the information is not written automatically within the xxxx.Designer.cs file. How can this behviour be changed?
You need more attributes:
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public override string Text { get; set; }
Reflector is a crucial tool for a .NET developer. It is immediately obvious what you need to do when you use it to look at the UserControl.Text property:
[Bindable(false), EditorBrowsable(EditorBrowsableState.Never), Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
}
}
Ho showed you what you need to do to cancel these attributes, too bad he didn't show you how he found out. Reflector is was free, download it from redgate.com or check the alternatives here : Something Better than .NET Reflector?
For serialization within the InitializeComponent(), all you need is the DesignerSerializationVisibilityAttribute:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]