Using NewtonsoftJson, and without knowing the entire 'model', how do you create a new parent object and set a child value, when the parent doesn't already exist?
Existing parent
//The parent already exists, but the child does not.
jobj["Parent1"]["Child"] = true;
File.WriteAllText(mypath, JsonConvert.SerializeObject(joj, Formatting.Indented));
//output
//Successfully creates new child
New parent
//The parent does not exist, nor the child.
//Throws null reference exception as jobj["Parent3"] doesn't exist
jobj["Parent3"]["Child"] = true;
File.WriteAllText(mypath, JsonConvert.SerializeObject(joj, Formatting.Indented));
JSON
{
"parent1": {
"child": true
},
"parent2": {
"child": true
},
Well, you need to check whether the parent exists, and create it if it doesn't.
JToken parent = jobj["Parent3"];
if (parent == null)
{
// parent object doesn't exist so create it
parent = new JObject();
jobj["Parent3"] = parent;
}
parent["Child"] = true;
To add a new JProperty you need to add use JToken.FromObject within the JProperty constructor.
eg
jobj.Add(new JProperty("parent3", JToken.FromObject(new Parent { Child = true})));
Related
I was wondering if it is possible to assign individual IDs to the child of a repeater in QML?
For example, if my repeater was to create 10 rectangles, how do I assign each of them a unique id? e.g. rec1, rec2, etc.
As already said above id is not a regular property and cannot be set or changed at runtime. You cannot reference this attribute, for example the following code will not work:
console.log(obj.id);
The nearest analogue of id from C++ is a variable name:
auto id = new Object();
when you can reference the name but cannot set or change it.
As for the issue, you can reference an item using objectName, or by using some specified access function, for example:
Row {
id:row
anchors.centerIn: parent
spacing: 5
Repeater {
id: container
model: 10
Text {
text:"item" + index
objectName: "item" + index
}
Component.onCompleted: {
container.itemAt(5).text = "changed1";
findChild(row, "item6").text = "changed2";
}
function findChild(obj, name) {
for(var i = 0;i < obj.children.length;i ++){
if(obj.children[i].objectName === name)
return obj.children[i];
}
return undefined;
}
}
}
Just add this property to any QML object that requires a unique id:
readonly property string uniqueId: `${this}`.substring(`${this}`.indexOf("(0x") + 2).replace(")", "")
I'd like to implement something like the following HTML helpers in MvcSiteMapProvider:
Html.MvcSiteMap().Previous()
Html.MvcSiteMap().Next()
However, I am quite new to their API, is it possible to do that, and if so, how?
You can accomplish this by building custom HTML helpers. I have answered this question already at GitHub and provided a working demo project, but I am copying here for reference.
The logic to walk up and down the document would look something like this, the rest of the code is for the most part boilerplate templated HTML helper code.
private static ISiteMapNode GetNextNode(ISiteMapNode startingNode, IDictionary<string, object> sourceMetadata)
{
ISiteMapNode nextNode = null;
if (startingNode.HasChildNodes)
{
// Get the first child node
nextNode = startingNode.ChildNodes[0];
}
else if (startingNode.ParentNode != null)
{
// Get the next sibling node
nextNode = startingNode.NextSibling;
if (nextNode == null)
{
// If there are no more siblings, the next position
// should be the parent's next sibling
var parent = startingNode.ParentNode;
if (parent != null)
{
nextNode = parent.NextSibling;
}
}
}
// If the node is not visible or accessible, run the operation recursively until a visible node is found
if (nextNode != null && !(nextNode.IsVisible(sourceMetadata) || nextNode.IsAccessibleToUser()))
{
nextNode = GetNextNode(nextNode, sourceMetadata);
}
return nextNode;
}
private static ISiteMapNode GetPreviousNode(ISiteMapNode startingNode, IDictionary<string, object> sourceMetadata)
{
ISiteMapNode previousNode = null;
// Get the previous sibling
var previousSibling = startingNode.PreviousSibling;
if (previousSibling != null)
{
// If there are any children, go to the last descendant
if (previousSibling.HasChildNodes)
{
previousNode = previousSibling.Descendants.Last();
}
else
{
// If there are no children, return the sibling.
previousNode = previousSibling;
}
}
else
{
// If there are no more siblings before this one, go to the parent node
previousNode = startingNode.ParentNode;
}
// If the node is not visible or accessible, run the operation recursively until a visible node is found
if (previousNode != null && !(previousNode.IsVisible(sourceMetadata) || previousNode.IsAccessibleToUser()))
{
previousNode = GetPreviousNode(previousNode, sourceMetadata);
}
return previousNode;
}
I have a list and setting the list to the exact item that is in it's dataProvider would not select it programmatically. Here is the code:
if (list.selectedItem != iDocument) {
var length:int = documentsCollection.length;
for (var i:int;i<length;i++) {
jDocument = IDocumentData(documentsCollection.getItemAt(i));
if (jDocument.uid==iDocument.uid) {
list.selectedItem = IDocumentData(documentsCollection.getItemAt(i));
break;
}
}
}
There were two issues.
I had applied a sort to the ArrayCollection and the field was not in the item. I had copied code from another project and the field was "#name" since it was an XMLListCollection. The sort field should have been set to "name".
So when you set the selectedItem property it looks in the collection and if the collection has a sort then it looks in the findItem() call which does a compare function that checks if the item has the field name in the item. If not it throws an error. Since I had the incorrect field name an error was thrown. If an error is thrown then the pursuit to find the selected item is abandoned and selected index is -1.
Code from ListCollectionView.as:
try
{
return sort.findItem(localIndex, values, mode, insertIndex);
}
catch (e:SortError)
{
// usually because the find critieria is not compatible with the sort.
}
return -1;
Code from Sort.as:
var hasFieldName:Boolean;
try
{
hasFieldName = values[fieldName] !== undefined;
}
catch(e:Error)
{
hasFieldName = false;
}
if (hasFieldName)
{
if (!hadPreviousFieldName)
{
message = resourceManager.getString(
"collections", "findCondition", [ fieldName ]);
throw new SortError(message);
}
else
{
fieldsForCompare.push(fieldName);
}
}
The second issue was that the List uses an exact equality operator so it uses "===" instead of "==". This means that you have to make sure you are passing in the exact instance of the item in the list.
I'm trying to use Ember to dynamically create child views in a ContainerView.
The problem is those child views need data bindings to a value from an attribute given to the container view.
Here is a bit of code showing roughly what I'm doing:
ReferenceCat.EditorView = Ember.ContainerView.extend({
init: function(){
this._super();
if(this.get('model.type') != undefined){
this.modelTypeChanges();
}
},
modelTypeChanges : function(){
// 1st step: Remove all children of my view
this.removeAllChildren();
var model = this.get('model');
// 2nd step is to run through all of the type information
// generating the views that we need to actually
// fill in this reference
var tI = model.get('typeInfo');
var self = this;
tI.forEach(function(field){
// Now we have a field
switch(field.type){
case "string":
// add new child view here with data binding to data.<field.name>
break;
}
});
}
});
And this class is referenced like this:
{{view ReferenceCat.EditorView
modelBinding=model}}
In your modelTypeChanges function instead of using a switch statement to create the different types of childViews you need to override the ContainerView's createChildView function (http://emberjs.com/api/classes/Ember.ContainerView.html#method_createChildView). The createChildView function itself will return the instantiated childView and in that overidded function itself you can place your switch statement. So it will look something like this...
createChildView: function(view, attrs) {
switch(attr.type) {
case "string":
view = yourview //your view class here, it is overriding the default
break;
}
.....
...
//Once you place all your case statements above
//make sure to call the parents createChildView function.
//This line is actually creating the view you want with the
//properties that are defined in the object attrs
return this._super(view, attrs);
}
So make sure when you call your overridden createChildView function to pass it the object you want bounded in the childView as a property of the object you pass as its second parameter...
var self = this,
tempviewarray = [];
tI.forEach(function(field){
var view = self.createChildView(null, field);
tempviewarray.push(view);
});
// add all the instantiated views to the ContainerView as children views
this.pushObjects(tempviewarray);
Im trying to create a subtree using QTreeWidgetItem.
Here's code
m_pRoot = new QTreeWidgetItem(treeWidget);
m_pRoot->setText(0, "root");
m_pRoot->setData(0, Qt::UserRole, IT_ROOT);
createTreeItem(m_pRoot, m_pText, "subtree_1", IT_TEXT);
m_pRoot->setExpanded(true);
createTreeItem(m_pText, m_pPlainText, "subtree_2", IT_TEXT);
that's method:
void createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item, CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
}
It's ok when im creating a "subtree_1" with m_pRoot as root item, but it breaks down when i want to create "subtree_2" with m_pText as root item.
P.S PTR() equal *parent.
Cant understand what's the problem. Any suggestions?
If your PTR(QTreeQWidgetItem) macro yields QTreeWidgetItem*, then item is not initialized by createTreeItem function.
The simplest and most logical fix seems to change createTreeItem function to return new item:
QTreeWidgetItem* createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item,
CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
return item;
}
and use the returned value to initialize m_pText.