How to create control at runtime using app.config? - wpf-controls

I would like to create simple objects at runtime (textbox, label, etc) and add them to a Grid in my WPF application. My problem is that I need to define these in the app.config file. I am reading in the config data by using the “ConfigurationManager.GetSection” method. Shown below is an example of the XML that defines two textboxes. The Key values are always defined as Labels so the following defines two labels called “ID:” and “Name:” and two associated TextBoxes
<HardwareControls>
<add key="ID:" value="System.Windows.Controls.TextBox"/>
<add key="Name:" value="System.Windows.Controls.TextBox"/>
</HardwareControls>
At the moment I use the following code to create a TextBox object but need to modify it so that the control types are defined by the config data and not hardcoded. Can anyone help in how I would go about doing this based on me knowing the control type as defined by a string?
TextBox tb1 = new TextBox();
tb1.Width = 100;
tb1.SetValue(Grid.ColumnProperty, 1);
tb1.SetValue(Grid.RowProperty, i);
I can also see a situation where I may want to define additional values such as the textbox width in the config file. Is there a better solution to store this in the app.config as it looks like the “GetSection” method only supports a key/value pair (I may be rog in that assumption as I haven’t read too much about this yet).

You can use Activator.CreateInstance
Example:
string typeName = "System.Windows.Controls.TextBox";
Type type = Type.GetType(typeName);
object control = Activator.CreateInstance(type); // control is your TextBox

You can use Reflection to create a type from a string name - e.g.
http://en.csharp-online.net/CSharp_FAQ:_How_create_an_instance_of_a_type_using_only_its_name
or
How can I pass an argument to a C# plug-in being loaded through Assembly.CreateInstance?

Related

How to check if node has property without instancing?

I'm trying to check if a certain node type has a property
without actually needing to make an instance of it
like this:
print("z_index" in Position2D);
Classes in ClassDB
If we are talking about a build-in class (not a custom class that you created, but one that is part of Godot), you can use ClassDB to get the property:
var properties := ClassDB.class_get_property_list("Position2D")
Classes from Godot Scripts
If the class is not in ClassDB (which is the case custom classes), but you have the script, you can use the script to get the property list:
var properties := preload("res://custom_class.gd").get_script_property_list()
If you don't have the script, perhaps you can find it. This code uses the hidden project setting "_global_script_classes" to find the path of the script for a class given the name_of_class you are looking for, and loads it:
if ProjectSettings.has_setting("_global_script_classes"):
for x in ProjectSettings.get_setting("_global_script_classes"):
if x.class == name_of_class:
return load(x.path)
Addendum: This is no longer available in Godot 4.
Other classes
However, the above approach will not work for every type of script. In those cases, I'm afraid the best way is to instance it. You can still get the properties from the instance and cache them (perhaps put them in a dictionary) so that you are not creating a new instance every time you need to query:
var properties := (CustomClass.new()).get_property_list()
Query the properties
Regardless of how you got the property list, you can query them the same way. For example this code looks for a property with name "z_index" and gets its type:
var found := false
var type := TYPE_NIL
for property in properties:
if property.name == "z_index":
found = true
type = property.type
break
prints(found, type)
The type is a Variant.Type constant.
Theraot's answer is correct, since it provides a way to check attributes without creating an instance of a node/gdscript.
You can also check the properties of an existing instance of a node/scene by doing this:
if "attribute_name" in thing:
pass # do stuff here
Practical example; During a signal triggered by two Area2Ds colliding, check if one node's attribute item_type is set:
func _on_area_2d_area_entered(area):
if "item_type" in area:
print(area["item_type"])

How to set a List value with JScript

In FileNet, using FEM or ACCE, it is possible to use JScript in order to set attributes' values to an object. The official IBM guide provides this example (for Strings):
importClass(Packages.com.filenet.api.property.Properties);
importClass(Packages.com.filenet.api.constants.RefreshMode);
function OnCustomProcess (CEObject)
{
CEObject.refresh();
CEObject.getProperties().putValue("DocumentTitle", "Test1");
CEObject.save(RefreshMode.REFRESH);
}
But is it possible to do the same thing for more complex objects? I'm referring, in particular, to StringList type. There are no examples on the web, and defining a JS-like array doesn't work.
It is definitely possible to do this for more complex objects. Most of it is just following the path you would follow using Java, but changing the name of the variable types to var. Therefore the code for setting the value of a multivalue string property is as follows:
importClass(Packages.com.filenet.api.constants.RefreshMode);
importClass(Packages.com.filenet.api.core.Factory);
function OnCustomProcess (CEObject)
{
CEObject.refresh();
var list = Factory.StringList.createList();
list.add("Value 1");
list.add("Value 2");
CEObject.getProperties().putObjectValue("TestMultiValueProperty1", list);
CEObject.save(RefreshMode.REFRESH);
}
I often use the putObjectValue() method instead of the putValue() method because JavaScript sometimes has problems determining which type safe version of the putValue() it should use.
For a lot of examples you could go to the Global Configuration > Data Design > Add-ons section in the domain tab of the ACCE. The pre- and post-import scripts of the different Add-ons contain a lot of relevant JavaScript code.

Haxe Property - getters and setters versus #:isVar

My question is regarding properties in haxe.
If I understand it correctly, if I make property like this
var propertyInt(get, set):Int; according to haxe documentation it's not really a variable. But I can make it a variable by modifying it this way
#:isVar var propertyInt(get, set):Int;. Otherwise I need to make two methods:
function get_propertyInt()
return propertyInt;
function set_properyInt(i)
return propertyInt = i;
So my question is: does it matter if I'm using exclusively #:isVar var propertyInt(get, set):Int; ? For example I have more than 5 properties in my class and as you can imagine making this methods for every property could be huge pain in the rear. So what is the best approach?
Here's what the documentation has to say about physical properties (also known as backing fields):
A field is considered to be physical if it is either
variable
a property with the read-access or write-access identifier being default or null
a property with :isVar metadata
So you can set up a property that fully consists of calculated values. Think a read-only property giving you the area of a rectangle as a function of width and height, or think of a property that is backed by some other property and just returns/sets width and height in a different unit. Or maybe you just want to name your backing fields differently, say m_width and m_height.
The :isVar is helpful in situations where the property access rules etc. laid out above would let the compiler think that there is no backing field needed. In that case, the code would fail (from the docs again):
// This field cannot be accessed because it
// is not a real variable
public var x(get, set):Int;
function get_x() {
return x;
}
function set_x(x) {
return this.x = x;
}
By adding :isVar you basically tell the compiler that you absolutely want the backing field. The other option for your particular case would be to use default,default, in which case the compiler knows there is an automatic backing field required and access should be restricted according to the access level of the property (public or private):
public var propertyInt(default, default):Int;
In that case you might also use a variable directly, because the net effect is in essence the same:
public var propertyInt : Int;

How to use UVM factory's set_inst_override_by_name to override sequence item

I have two sequence item class a_packet and its extended class called bad_packet.
By default, a_packet type is used.
Trying to override a_packet instance with bad_packet, I am able to do it successfully by using set_inst_override_by_name in my uvm test,
factory.set_inst_override_by_name("a_packet","bad_packet", "*");
Now my question is: what if I don't want to use "*", how to know the full hierarchical path of the sequence item instance?
I was trying to utilise get_full_name() from inside the sequence item, right after it is received by the driver, to know the exact hierarchical path. It displayed:
uvm_test_top.env.a_agt.a_seqr.a_sequence.a_packet
But when I replaced the * with above path, the overriding is not happening.
factory.set_inst_override_by_name("a_packet","bad_packet","uvm_test_top.env.a_agt.a_seqr.a_sequence.a_packet");
Did I do something wrong?
Where you create your packet, you'll need to to specify the full path to the corresponding call to create(..):
packet = a_packet::type_id::create("packet", , get_full_name());
If you were using the uvm_do macro, you'll have to change to using the explicit sequence API:
packet = a_packet::type_id::create("packet", , get_full_name());
start_item(packet);
// ... randomize ...
finish_item(packet);
Idea is from this DVCon Paper, section IV.A.

How to auto-generate early bound properties for Entity specific (ie Local) Option Set text values?

After spending a year working with the Microsoft.Xrm.Sdk namespace, I just discovered yesterday the Entity.FormattedValues property contains the text value for Entity specific (ie Local) Option Set texts.
The reason I didn't discover it before, is there is no early bound method of getting the value. i.e. entity.new_myOptionSet is of type OptionSetValue which only contains the int value. You have to call entity.FormattedValues["new_myoptionset"] to get the string text value of the OptionSetValue.
Therefore, I'd like to get the crmsrvcutil to auto-generate a text property for local option sets. i.e. Along with Entity.new_myOptionSet being generated as it currently does, Entity.new_myOptionSetText would be generated as well.
I've looked into the Microsoft.Crm.Services.Utility.ICodeGenerationService, but that looks like it is mostly for specifying what CodeGenerationType something should be...
Is there a way supported way using CrmServiceUtil to add these properties, or am I better off writing a custom app that I can run that can generate these properties as a partial class to the auto-generated ones?
Edit - Example of the code that I would like to be generated
Currently, whenever I need to access the text value of a OptionSetValue, I use this code:
var textValue = OptionSetCache.GetText(service, entity, e => e.New_MyOptionSet);
The option set cache will use the entity.LogicalName, and the property expression to determine the name of the option set that I'm asking for. It will then query the SDK using the RetrieveAttriubteRequest, to get a list of the option set int and text values, which it then caches so it doesn't have to hit CRM again. It then looks up the int value of the New_MyOptionSet of the entity and cross references it with the cached list, to get the text value of the OptionSet.
Instead of doing all of that, I can just do this (assuming that the entity has been retrieved from the server, and not just populated client side):
var textValue = entity.FormattedValues["new_myoptionset"];
but the "new_myoptionset" is no longer early bound. I would like the early bound entity classes that gets generated to also generate an extra "Text" property for OptionSetValue properties that calls the above line, so my entity would have this added to it:
public string New_MyOptionSetText {
return this.GetFormattedAttributeValue("new_myoptionset"); // this is a protected method on the Entity class itself...
}
Could you utilize the CrmServiceUtil extension that will generate enums for your OptionSets and then add your new_myOptionSetText property to a partial class that compares the int value to the enums and returns the enum string
Again, I think specifically for this case, getting CrmSvcUtil.exe to generate the code you want is a great idea, but more generally, you can access the property name via reflection using an approach similar to the accepted answer # workarounds for nameof() operator in C#: typesafe databinding.
var textValue = entity.FormattedValues["new_myoptionset"];
// becomes
var textValue = entity.FormattedValues
[
// renamed the class from Nameof to NameOf
NameOf(Xrm.MyEntity).Property(x => x.new_MyOptionSet).ToLower()
];
The latest version of the CRM Early Bound Generator includes a Fields struct that that contains the field names. This allows accessing the FormattedValues to be as simple as this:
var textValue = entity.FormattedValues[MyEntity.Fields.new_MyOptionSet];
You could create a new property via an interface for the CrmSvcUtil, but that's a lot of work for a fairly simple call, and I don't think it justifies creating additional properties.

Resources