I have a viewmodel which has some observables and observableArrays.
Depending on the page you are looking at it will fill up a certain observable or observable array. and then map it.
However from time to time there might be a subproperty which has currently a null value in it which i can create a new instance of through an api call (default values and so on server sided handled, seperation of concerns in mind, no Business Logic client sided!).
So when i do the $.get() request i placed it directly in the object and the data shows up in my viewmodel, however it is not mapped to the fields where they are bound to?
Binding works, but only one way (read). What do i miss? The api call (example), which places everything in the vm:
$.get('../../../../../api/addresses/?id=new&subjectid=' + subjectid, null, vm.currentSubject()['CurrentAddressInfo'])
Related
I am brand new to ASP.Net MVC. So, keep that in mind. :)
I have a view with nested collections, with fields that get updated by the end user.
I have the updated model data successfully coming back from an AJAX call to my controller.
So... now i have a model with nested collection objects - where each item in collection also carries a collection. (BTW) This is a very low volume app.
I am not currently using EF - strictly using old fashion SQL calls and sprocs.
Is there an easy way to determine which values of my collection have been updated without out drawing out the whole collection from database again and iterating the whole thing? ugh...
You would use Knockout Js and Observable Arrays will help you to track all changes on the View. Knockout tracks and updates all things automatically, you just need create Update() method and mark changable variables as observables.
I'm currently looking for a solution to my issue: In our ASP.NET MVC application there are pages that are used for realtime data visualization of industrial devices. When the page gets loaded, a loading icon is shown while I fetch the viewmodel data with the current values for all the datapoints from a database. That works quite well, but it is static, by which I mean that the values don't change on the page after it finished loading. The web application itself uses a TCP listener that receives messages with values from the devices. These messages (which basically consist of a device id, a datapoint id and the value) don't arrive in fixed intervals but event-based, e.g. when a temperature value changes 0.5 K up or down.
On my page I have some graphical widgets like gauges and many other elements that correctly show the values from the initial data that gets loaded on the page load. They are bound to the Knockout viewmodel.
The problem is this: whenever a new value arrives on the server, I want to show it on the page without the need for a reload. I definitely don't want to re-transmit the whole viewmodel with some hundred datapoints on every message that arrives on the server (appr. 1 to 15 per second). In order to achieve that, I implemented the SignalR framework, which really works great. With that mechanism I now receive the new value in the client window (that means, I receive it in Javascript and now have a value object like described below).
What I need now is this: as every viewmodel gets built dynamically, they are all different. The object and properties tree is not the same for two devices, so each of them can have varying levels of subobjects. The only thing that is the same is the structure of the object that actually holds the value for each datapoint: it always consists of the aforementioned device id, the datapoint id and the value.
I need a way to update the double-type value inside the value object within the viewmodel whose device id and datapoint id match the newly arrived value message (that also consists of these two address-like ID's and the value).
I hope I got the idea across. Is there a way to do this? What would be the best practice for such a mechanism? I recently switched to Knockout-MVC (kMVC nuget package), but I'd also go back to "pure" Knockout.js and some additional scripting if that helps.
Thanks for your help and recommendations!
http://nthdegree.azurewebsites.net/mvvm-2/
Here is an article speaking to the Knockout mapping plugin
The general idea is that you should have your view model code which loads your model.
You would bind up your view model which will have a property you load from the server with an ajax call (see bottom of article).
You then just update the model with the result with
ko.mapping.fromJS(newData, mapping, modelToUpdate)
var mapping = {}; //define your mapping (see documentation or blog post)
function ViewModel(){
var self = this;
self.model = ko.mapping.fromJS({}, mapping);
self.hub = $.connection.myHub();
self.hub.client.updateModel = function(data){
ko.mapping.fromJS(data, mapping, self.model);
};
self.hub.start().done(function(){
//you could either make a call or have the "OnConnected" method trigger an 'updateModel'
});
}
ViewModel properties when linked to a DOM element allows editing which is actually updating the data in the KO observable array. Is it possible for you to change the "graphical widget"'s value (assuming that it is using some property to maintain height and width) using the IDs which you said are consistent?
I have not tested; the other option is to use KO foreach loop and update the related value.
I have a network service that provides a number of key-value pairs. The collection is huge and the available keys are changing over time. My goal is to be able to bind to this collection in either Visual Studio 2013 or Blend using the properties window in design mode (or intellisense in XAML). This of course requires the service client object to somehow be initialized during design mode to connect to the service and expose the keys as bindable properties.
I have been searching a lot about "ObjectDataSource" but my problem is that I cannot dynamically change the properties of this object.
What type of object should I choose as my data context?
How can I populate it during design mode?
Any ideas or suggestions towards how this could be implemented would be great.
You can set your data context to any object - you get dynamic updates if
the object implements INotifyPropertyChanged (http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx)
or is observable (like ObservableCollection<> (http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx)).
If your goal is to create an observable dictionary, have a look at this post: http://blogs.microsoft.co.il/shimmy/2010/12/26/observabledictionarylttkey-tvaluegt-c/
The object data provider can have it's data source set to any object too - the dynamic updates will occur if the object is as stated above. In addition, you can declaratively set the objectDataSource's values in xaml - but this doesn't appear to be something you want to do.
Note: You don't change the properties of the object data source - you change the object that it is wrapping for you.
If you want to be able to control the selected item of something like a list (a bit like the Winforms BindingSource)- take a look at ICollectionView (http://msdn.microsoft.com/en-us/library/system.componentmodel.icollectionview(v=vs.110).aspx) which can be created by wrapping up your actual data source (same observable rules apply to get dynamic updates) using CollectionView (see http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.getdefaultview(v=vs.110).aspx)
So - to answer the rest of your question, one solution is to create an observable collection of observable objects (wrapping your key value pairs) and set that as your data context (or set it as your objectDataProvider's source, and bind your Xaml accordingly. This isn't the only way, but a quick google will show you others.
Edit Design mode
For design time data - look at using the design mode flags - an example is here: http://www.arrangeactassert.com/how-to-use-designdata-to-populate-controls-with-design-time-data-in-silverlight-and-wpf/
A list of (Silverlight design time attributes): http://msdn.microsoft.com/en-us/library/ff602277%28v=vs.95%29.aspx
I've never actually tried the design time stuff, so that's all I got!
Hth.
I have a model that I am retrieving from a cache, which I use on several pages. Part of the model has a property called Breadcrumb - which is a collection of breadcrumb elements and is updated like this:
model.Breadcrumbs.Add(UrlUtilities.Urls.DesignerJoinConfirmation, "Feedback Confirmation", "Thank you for your feedback");
My problem is that even though I am getting the model back from the cache, when I add another breadcrumb after it is returned from the cache (eg for child pages I would add the latest page onto the end), it is then updating the cached model. Is there a way of updating the model and not updating the cache?
I have tried creating a temp model and reassigning the cached object to it like so:
Model model = GetCachedModel();
Model tempModel = new Model();
tempModel = model;
And then updating the tempModel but this also updates the cached object. The only way I have found to stop the cache object being updated is by making the tempModel and then reassigning each property separately from the cached model but surely this negates the need for caching if I have to reassign all the properties each time. Is there a simpler way to update a cached object without updating the cache itself?
I think you are mixing references to objects with the objects. When you retrieve the model from the cache you are really only getting another reference to the same object that the cache is referencing. Thus any changes made via your reference will also be visible via any other references.
There are two approaches to avoiding this:
Clone—copy—the model instance from the cache. This will require assistance from the implementation to do in general. Remember this will need to be a deep copy, any properties and fields of the model that are themselves references will also need the referenced object to be copied. Recursively.
Don't put the breadcrumbs in the model. If difference uses of the same model need different values for this property then it does not belong in the model.
(There are also options using value types—which are copied rather than referenced—but good practice is (1) vale types should be small (not many fields), and (2) immutable.)
Model model = GetCachedModel();
Model tempModel = new Model();
tempModel = model;
That's not going to work. You are creating a reference to a new instance (tempModel) and then overwriting that reference with a reference to the original from the cache.
Hello fellow developers.
First of all I apologize beforehand for the wall of text that follows, but after a day going crazy on this, I need to call for help.
I've stumbled across a problem I cannot seem to solve. I'll try to describe the scenario in the best possible way.
Task at hand: in an existing Asp.Net Mvc application, create a lookup table for an integer field, and use the textual value from the lookup in the editing view. When saving, we must first check if the lookup already has a corresponding text value for the same Root ID. If there is, use that. Otherwise, create it and then use it.
The structure:
The data model is a graph of objects where we have the root object, a collection of level A child objects, and every level A child object has a collection of level B child objects, so something like this:
Root (with fields)
Level A child (with fields) x n
Level B child (with fields) x n
The field we have to handle is on the LevelB objects.
There is a single Mvc view that handles the whole data. For collection objects, all fields are named like levelA1levelB1MyField, levelA1levelB2MyField, etc so every single field has unique name during the post. When the post happens, all values are read through a formCollection parameter which has average 120/130 keys. The keys are isolated by splitting them and looping on the numerical part of the names, values are read and parsed to the expected types and assigned to the object graph.
The datalayer part backing the object graph is all stored procedures, and all the mapping (both object to sproc and sproc to object) is hand written. There's a single stored procedure for the read part, which gets multiple datasets, and the method calling it reads the datasets and creates the object graph.
For the saving, there are multiple sprocs, mainly a "CreateRoot" and "UpdateRoot". When the code has to perform such tasks, the following happens:
For create scenario, "CreateRoot" is called, then the sprocs "CreateLevelA" and "CreateLevelB" are called in loop for each element in the graph;
For update scenario, "UpdateRoot" is called, which internally deletes all "LevelA" and "LevelB" items, then the code recreates them calling the aforementioned sprocs in loop.
Last useful piece of information is that the "business objects graph" is used directly as a viewmodel in the view, instead of being mapped to a plain "html friendly" viewmodel. This is maybe what is causing me the most trouble.
So now the textbox on the view handles an "integer" field. That field must now accept a string. The field on LevelB must remain an integer, only with a lookup table (with FK of course) and the text field from the lookup must be used.
The approaches I tried with no success:
My first thought was to change the datatype on the property MyField from integer to string on the object, then change the sprocs accordingly and handle the join at sproc level: I'd have a consistent object for my view, and the read/write sprocs could translate from string to integer and viceversa, but I can't do that because the join keys to retrieve the integer when writing are part of the Root item (as I stated in the first lines of this wall of text), which I don't know in the CreateLevelB sproc, and changing the whole chain of calls to pass those parameters would have a huge impact on the rest of the application, so no good.
My next try was to keep things "as they are" and call some "translation methods": when reading, pass the integer to the view, and there call the translation method to display the text value. When saving, use the posted text to retrieve the integer. The save part would work, I'd have all the parameters I need, but for the read part, I'd have to instantiate the "data access layer" and call its method at View level, and there's no need to explain why that is a very bad choice, so I ruled this out too.
Now I'm out of options (or ideas anyway). Any suggestion to solve this is very welcome, and also if something is not clear enough just point it out and I will edit my post with more accurate information.
Thanks.
This is not a real answer but you could rip out all sprocs and use the updating facilities of an OR mapper. This will resolve all the layering issues. You just update data how you see fit and submit at the end.
I guess this would also make the questions around "should I use an int or a string" go away.
Edit: After reading your comment I thought of the following: Do not implement alternative 1. You rather want to sacrifice code quality in the view than in the data storage model. The last one is more important and more centrally used.
I would not be too concerned with messing up the view by calling the DAL from it or the like. Changes in a view are localized and do not mess up the application's architecture. They just degrade the view.
Maybe you could create a view model in your controller and do the translations between DAL-model and view model? Or is that pattern not allowed?