How to convert List<Objects> to an ObservableRangeCollection - mvvm

I am using Xamarin Forms and their templates come with MvvMHelpers object to be used in the ViewModel as ObservableRangeCollections. I know ObservableCollections. If you try to do :
ObservableRangeCollection<Object> collection = new ObservableRangeCollection<Object>();
List<Object> objects = new List<Objects>();
collection.ReplaceRange(objects);
//error invalid type
Does anyone know how to use an ObservableRangeCollection? There is nothing on it in Google, Bing or StackOverflow.
Try the search you'll see Xamarin is promoting something so new that nobody knows what it is.

ObservableRangeCollection is a helper class by the Xamarin Evangelist James Montemagno.
The source is available in his github:
https://github.com/jamesmontemagno/mvvm-helpers
ObservableRangeCollection intends to help when adding/replacing Collections to a ObservableCollection.
In a "regular" ObservableCollection, for each new item added to the Collection, a OnCollectionChanged event would raise.
This is where ObservableRangeCollection gets in. It allows to replace/add elements to the Collection without firing an event for each element.

ObservableRangeCollection is subclassed from ObservableCollection.
So in your example, substitute your <T>, i.e:
ObservableRangeCollection<string> collection = new ObservableRangeCollection<string>();
List<string> objects = new List<string>();
collection.ReplaceRange(objects);
Consult the code here: https://github.com/jamesmontemagno/mvvm-helpers/blob/master/MvvmHelpers/ObservableRangeCollection.cs

This is not something that new. There's plenty of code using ObservableCollection.
What you are trying to achieve can be done like this:
List<Object> myList = new List<Objects>();
ObservableCollection<Object> myCollection = new ObservableCollection<Object>(myList);
Read more about ObservableCollection.

Check out my answer here, which is an enhanced version of ObservableRangeCollection optimized for less event raising and reuse of items in UI.

Related

Saving to-do list items to be reviewed later?

I am extremely new to Flutter, so please forgive my ignorance and please explain things to me like I am a toddler.
I would like to implement a to-do list into my app similar to this project: https://github.com/ishrath-raji/todoey-flutter
It's just a basic list where users can add items, cross them out, and delete them. Very simple.
However, I have absolutely no idea how to take the items that users enter into the to-do list and store them in memory so that the user can review them later.
I've tried googling around, but all the answers I've seen are above my understanding and/or written in a way that is difficult to follow.
Any help would be very much appreciated!
I assume you have a view / page, where the user can give all the necessary information for the new ToDo item. This means you have a class representing a ToDoItem.
class ToDoItem {}
You will want to store them in some List.
As you probably want this list of ToDo items to be accessbible everywhere within the map, you should start researching the topic "state management".
As a starting point, just to name the easiest of all solutions, you could use Riverpod and declare one global variable:
final todoListRereference = StateProvider<List<ToDoItem>>((ref) => <ToDoItem>[]);
Now you have a list of ToDoItem which is accessible from everywhere in your app, provided you follow the steps to make Riverpod providers accessible everywhere. For example, in every build method you can use
final todoList = ref.watch(todoListRereference);
and you have access to all the stored ToDoItems.
In the case of your ToDoItem you can create with all the user information, you will have a construction like:
onPressed: () {
final todoItem = ToDoItem(...);
final todoListProvider = ref.read(todoListReference.notifier);
todoListProvider.state = [... todoListProvider.state, todoItem);
}
I just assumed it would happen after the user clicked something and the onPressed method of the according button is triggered.... However, first you create the ToDoItem. Then you access the List we made accessible with the reference. Then we change the "state" of that provider to a new state which is defined as all the old ToDoItems plus the newly created one.
If you have any pages in your app where you can see all the ToDoItems, you will now see one more.
I hope this is okay as a starting point.

syncfusion ej grid javascript method

I am very new to syncfusion controls for mvc. While exploring how to set dynamic datasource to grid, I came across this line of javascript code which I cannot understand. I have been through the javascript api docs for ej grid but couldn't find the meaning.
var obj = $("#Grid").ejGrid("instance");
If someone can explain the meaning and point out some reference documentation, I will be highly grateful.
The example I came across
https://help.syncfusion.com/aspnetmvc/grid/how-to
The javascript api I have been through
https://help.syncfusion.com/api/js/ejgrid#members:datasource
P.s: I know from a comment I came across that this has something to do with current instance of ej grid but I would like a solid understanding via a reference so I can understand.
From my little experience with Syncfusion controls the documentation explaining how to perform tasks is not well stated. If you have a license you can ask questions in their forum but I can tell you what little I learned perusing their forum.
In their JS 1 version
var obj = $("#Grid").ejGrid("instance");
and in their JS 2 version
var obj = document.getElementById('Grid').ej2_instances[0];
The variable obj appears to get an object reference to the grid identified by the id Grid. I am not sure what the instance value refers to other than the examples in the documentation show it and it works when it is used.
Not sure if I was much help.
In the Below code example Grid – Grid ID and you can take the Grid instance using the above code example. From the instance you can get the details regarding the column, dataSource, filterSettings, sortSettings etc currently applied to ejGrid. We have given support to customize the Grid using several public method. You can call those method by taking the Grid instance.
#(Html.EJ().Grid<EJGrid.Models.Order>("Grid")
.Datasource((IEnumerable<object>)ViewBag.datasource)
.AllowPaging()
.Columns(col =>
{ col.Field("OrderID").HeaderText("Order ID").TextAlign(TextAlign.Right).Width(75).Add();
col.Field("EmployeeID").HeaderText("Employee ID").TextAlign(TextAlign.Right).Width(90).Add();
col.Field("Freight").HeaderText("Freight").Format("{0:c}").TextAlign(TextAlign.Right).Width(90).Add();
col.Field("ShipCity").HeaderText("Ship City").Width(90).Add();
col.Field("Child.Test").HeaderText("TEst").Format("{0:c}").Width(90).Add();
col.Field("ShipCountry").HeaderText("Ship Country").Width(90).Add();
})
)
<script>
var obj = $("#Grid").ejGrid("instance");
var value = $("#colValue").val();
//Add custom parameter to the server
var query = new ej.Query().addParams("EmployeeID", value);
//Creating ejDataManager with UrlAdaptor
var dataManager = ej.DataManager({ url: "/Home/GetData", adaptor: new ej.UrlAdaptor() });
var promise = dataManager.executeQuery(query); promise.done(function (e) {
//Assign the result to the grid dataSource using "dataSource" method.
obj.dataSource(e.result);
</script>
To update the Grid, you can use dataSource() method. To call that method you need to take the Grid instance and call that method.
Refer the below API documentation for your reference
https://help.syncfusion.com/api/js/ejgrid#methods:datasource - used to update the Grid dataSource dynamically
https://help.syncfusion.com/api/js/ejgrid#members:datasource - returns the Grid dataSource.
Please get back to us if you have further queries.

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

GWT Editor Framework: Drop Down List

I'm looking for someone to point me in the right direction (link) or provide a code example for implementing a drop down list for a many-to-one relationship using RequestFactory and the Editor framework in GWT. One of the models for my project has a many to one relationship:
#Entity
public class Book {
#ManyToOne
private Author author;
}
When I build the view to add/edit a book, I want to show a drop down list that can be used to choose which author wrote the book. How can this be done with the Editor framework?
For the drop-down list, you need a ValueListBox<AuthorProxy>, and it happens to be an editor of AuthorProxy, so all is well. But you then need to populate the list (setAcceptableValues), so you'll likely have to make a request to your server to load the list of authors.
Beware the setAcceptableValues automatically adds the current value (returned by getValue, and defaults to null) to the list (and setValue automatically adds the value to the list of acceptable values too if needed), so make sure you pass null as an acceptable value, or you call setValue with a value from the list before calling setAcceptableValues.
I know it's an old question but here's my two cents anyway.
I had some trouble with a similar scenario. The problem is that the acceptable values (AuthorProxy instances) were retrieved in a RequestContext different than the one the BookEditor used to edit a BookProxy.
The result is that the current AuthorProxy was always repeated in the ValueListBoxwhen I tried to edit a BookProxy object. After some research I found this post in the GWT Google group, where Thomas explained that
"EntityProxy#equals() actually compares their request-context and stableId()."
So, as I could not change my editing workflow, I chose to change the way the ValueListBox handled its values by setting a custom ProvidesKey that used a different object field in its comparison process.
My final solution is similar to this:
#UiFactory
#Ignore
ValueListBox<AuthorProxy> createValueListBox ()
{
return new ValueListBox<AuthorProxy>(new Renderer<AuthorProxy>()
{
...
}, new ProvidesKey<AuthorProxy>()
{
#Override
public Object getKey (AuthorProxy author)
{
return (author != null && author.getId() != null) ? author.getId() : Long.MIN_VALUE;
}
});
}
This solution seems ok to me. I hope it helps someone else.

MVC2 sending collections from the view a controller via json

I've been looking on forums for 2 days now and can't find a good answer so I'll just post it.
I appear to be having a problem posting JSON back to the controller to save. The JSON should map to model view but it keeps getting default(constructor)values rather then the values from the POST.
We have a series of JS widgets that contain a data field with json in them. We do all our data manipulation in these widget objects on the client side. When a user wants to save we grab the data we need from the widgets involved and we put it into another JSON object that matches a ViewModel and POST that back to the server.
For example:
$("#Save").click(function () {
if (itemDetails.preparedForSubmit() && itemConnections.preparedForSubmit()) {
itemComposite.data.Details = itemDetails.data;
itemComposite.data.Connections= itemConnections.data;
$.post(MYURL, itemComposite.data);
} else {
alert("failed to save");
}
});
The preparedForSubmit() method simple does stuff like any validation checks or last minute formatting you might need to do client side.
The itemDetails widgets data matches a ViewModel.
The itemConnections widgets data matches a collection of ViewModels.
The Controller looks like this:
[HttpPost]
virtual public JsonResult SaveItemDetailsComposite(ItemComposite inItemData)
{
if (ModelState.IsValid)
{
try
{
_Mapper.Save(itemComposite.Details , itemComposite.Connections);
return Json(true);
}
catch (Exception ex)
{
_log.Error("Exception " + ex.InnerException.Message);
throw;
}
}
return Json(SiteMasterUtilities.CreateValidationErrorResponse(ModelState));
}
The ItemComposite Class is a simple View Model that contains a single itemDetails object and a collection of itemConnections. When it returns data to here it is just getting the default data as if it got a new ItemComposite rather than converting the POST data.
in Firebug I see the data is posted. Although it looks weird not automatically formatted in firebug.
Are you saying that itemComposite.data is formatted as a JSON object? If so, I'm pretty sure you're going to have to de-serialize it before you can cast it to your object. Something like:
ItemComposite ic = jsSerializer.Deserialize<ItemComposite>(this.HttpContext.Request.Params[0]);
You may want to look into a framework like JSON.NET to ensure that your data is being serialized properly when it gets supplied to your Action.
JSON.NET seems like it's one of the main stream frameworks: http://json.codeplex.com/releases/view/43775
Hope this helps.
Cory
You could also use the JSON Serializer in WCF: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx
SO wouldn't let me put both links in one answer, sorry for the split answer.
Thanks everyone. I think I have solved my problem and I'm pretty sure that I had four issues. For the most part I followed thatSteveguys's suggestion and read more on this article: http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx
Using jQuery's post() method and specifying json as the type didn't seem to actually send it as json. By using the ajax() method and specifying json it sent it as json.
The JSON.serialize() method was also need to cleanly send over the json.
Also my ViewModel design was a big problem. We are using the MS code analytic build junk and it didn't want me having a setter for my collections in the ViewModel. So me being from a java/hibernate world, thought it didn't need them to bind and it would just come in as a serialized object magically. Once I just suppressed the error and reset up my setters. I am getting the collections now in my controller.
I believe using the MVC2 Future's Value Providers are doing something but it still doesn't convert json dates robustly, So I am still investigating the best way to do that.
I hope my issues help out others.
UPDATE: using this method to update collections of data appears to be super slow. A collection with 200 entries in it and 8 fields per entry takes 3 minutes to get to the controller. Just 1 or 2 entries take very little time. The only thing I know of that is happening between here is data binding to the model view. I don't know if MVC2 provides a easy way to send this much data and bind it.