Basically my scenario is the following: I have 1 View bound to a ViewModel, with a List of items(the items' class is a class in my Model). Every time an item is selected from the list in this 'List View', its fields are edited in another, 'Details View'. This is identical to the Customer Management sample scenario, where a customer is selected from the List (in a 'List View') and the the Customer's details can be changed in a 'Details View'. The added quirk in my scenario, is that I want the changes done to the item in the Details View, to be reflected back in the List View. The changes are saved in DB from the Details View.
Also, depending on the changes done in the Details View, the item can be removed from list in the first View. Note that this is not deleting the record from the DB, because the list in the List View is just a filtered list of the items in the DB. I figured out two possible ways that I can do this:
By binding the 2 Views to the same View Model
EDIT: How do I call the second view? Will the second view actually use the same instance of the shared ViewModel?
-or-
2. By passing the item selected in the List View by reference to the Details View. Therefore in this case, I'm maintaining the 1-View-to-1-ViewModel mapping.
My questions are:
how can I implement scenario 1,
in 2, does the Init() method(used in conjunction with the ShowViewModel() method) support passing parameters by
reference?
I would be grateful, if you could include code snippets/examples in your answers.
Thanks a lot in advance,
binding 2 Views to the same View Model
You are free to set the ViewModel property on any View manually if you wish to. Simply set ViewModel = foo; before the call to base.OnCreate(), base.OnNavigatedTo() or base.ViewDidLoad()
in 2, does the Init() method(used in conjunction with the ShowViewModel() method) support passing parameters by reference?
MvvmCross does not support passing objects between ViewModels. On Windows Phone navigations are performed by url parameters. On Android, navigations are performed by Intents - these underlying mechanisms simply do not let you pass actual object references.
In general I handle this situation using messaging from the data store to the ViewModel
I would be grateful, if you could include code snippets/examples in your answers.
You can see how I typically do this in N=12 to N=15 in http://mvvmcross.wordpress.com/
Related
Maybe my question is a nooby one, but i really try to understand how to implement the following operations:
How to add item for a list without the need of rebuilding all list.
How to update a class instance property value.
Does BLoCProvider used only once in a class?
===> I'm asking those question because i see that BLoC working with 'Equatable' and that in a the state class there is always a need to bring default value to the state we provide to the view class.
Another Question (what change the view and operate the state):
Does i need to bring always a list in order for example to update an item from the list or only changing the state+emit(in cubit) will change the state of the application, maybe it realted to BLocListener?
Suppose I have three interface controllers which are all linked by push segues.
InterfaceController1 -pushSegue-> InterfaceController2 -pushSegue-> InterfaceController3
InterfaceController1 has table which will house the data from the class below.
So, suppose I have class:
class manageData {
var data1:String?
var data2:String?
}
and this class is supposed to hold the data from InterfaceController2 and InterfaceController3.
So InterfaceController1 creates a manageData object and passes it to InterfaceController2 using the contextForSegueWIthIdentifier method. InterfaceController2 then adds to its data to the manageData object and passes it along to InterfaceController3 using the contextForSegueWIthIdentifier method as well.
Now my question is, once InterfaceController3 adds its data to the object, how do I pass that complete object back to InterfaceController1 with the data filled in so InterfaceController1 can add the data to the table? Hopefully I've made this clear enough. I don't have any actual code to represent this because I have no idea how to implement it yet.
So the way I solved this issue was to create a singleton class which held all my data throughout the different controllers. Then when I reach the last controller and send my data to the singleton, I pop back to the root controller.
When I'm back in the root controller, in the awake method, I call a function I made called loadTableData() which automatically takes information from the singleton when it awakes and loads it in the table. Seems to work perfectly for now but I don't know any potential issues that can come up with this method.
Being able to share data between multiple view controllers and doing that in a way that makes use of recommended patterns such as MVC seems to be essential to create good apps, but my problem is that these things aren't clear at all for me.
I am conscient that this question is really dense, but for things to be clear I think you really need to understand the whole thing.
First of all we need to be sure of what Model, View and Controller are doing, here is how I would describe them, please tell me if I'm right about that:
Model : a class that's responsible for managing data, and only that (for example, a class that will go on the web to retrieve information, such as weather forecast).
View : a view is an object that's displayed to the user, who can often interact with it, that's the objects that you can drag and drop in Interface Builder (for example a button) and you might also create one from scratch, or custom an already existing one by subclassing it.
Controller : a controller is responsible for managing a view and its subviews, it receives events (such as viewDidLoad, or even when the user taps a button) and can react to it, for example, it might change the text of a label.
Now about the way they are interacting between each other, I'd say that the controller is between the view and the model, it's managing the view and might ask for data to the model. In addition to receiving events from the view, it might also receive events from the model, for example, if the controller asks to the model for a specific data on the web (let's say if it asks weather for a specific city) the data won't be available immediately, instead, the model will notify the controller so that it can update the view with the data it received. Am I right?
One of the first thing I'm wondering is if an object could be considered as a model if it isn't here to retrieve data, but to do other things that are simply not related to the view, for example, could an object that's responsible for communicating and managing a bluetooth accessory considered as a model ? Could an object that sends data to a cloud considered as a model ? And what about a Tic Tac Toe AI ?
Then, singleton instances, I often heard of them when an app had to share data between multiple views, but first of all, I never really understood why it was necessary to use them in this case ?
Then, here is a singleton that I found in an article of the We Heart Swift website.
class Singleton {
struct Static {
static let instance = Singleton()
}
class var sharedInstance: Singleton {
return Static.instance
}
}
Singleton.sharedInstance
The problem if that I have had difficulties to find anywhere more details about why it's written in this way, and most of all, can a singleton have an initializer that takes arguments? How to add properties and methods to a singleton like this one? What are exactly the Static structure and the sharedInstance?
My last question is about why, technically, does a singleton makes it possible to get an access to things we have defined somewhere else? What I mean is that if I create an instance of let's say, a Dog class in my AppDelegate, and if I want to access to this specific instance in a view controller, then it wouldn't be possible, so how does singleton makes that possible under the hood?
EDIT : Oh, and, is the use of singletons recommended by Apple?
Thank you.
It has to do with the static in the struct. Static is essentially a class variable that persists for every instance of that class, so when you make the shared instance static, every time you access it, even from another instance of Singleton.instance it is the same variable because it is static. It persists amongst instances. However, Swift does not support class variables yet, so when it does, that should quickly replace the Struct syntax that is common of singletons. It is very similar to static variables in java.
For example:
class Singleton {
var someVar = 0
struct Static {
static let instance = Singleton()
}
}
to create a singleton with a variable and the following to access it:
let foo = Singleton.Static.instance
foo.someVar = 11
let bar = Singleton.Static.instance
println(bar.someVar) // Prints 11
As you can see, bar.someVar was never set, and that is because the variable for the shared instance was set, so it prints 11.
I am creating a web based software using Asp.net MVC 5 with EF framework on Visual Studio 2013.
I have a view page which needs to display two partial views at a given time. The partial views are associated with 2 model classes thus will be be from two Controllers. How to specify which frame the partial view should be displayed?
I'm new to MVC 5 so I am unable to provide a more detailed description. Any suggestion that can get me the result below would be helpful
At least a couple of options:
1 #Html.Action
Just use #Html.Action (twice) to render the partial views using separate controller calls:
e.g.
#Html.Action("action1", "Controller", new { id = Model.idOfPart1 }
#Html.Action("action2", "Controller", new { id = Model.idOfPart2 }
Where the id's are the key/lookup values you would normally pass to a control if they were full views.
Action() causes a full call to the action of the controller specified and renders the result in-place in the parent view.
2 #Html.Render
If instead you wish to pass a combined ViewModel to the parent view, and send parts of the model to each partial view, you can use #Html.Partial:
#Html.Render("ParialView1", Model.model1);
#Html.Render("PartialView2", Model.model2 }
This version passes specific models requesting each partial view render with it.
Render() is probably the most common model for passing data to partial views, but it really depends on how you want to pass the data around and how your controllers are structured. I always use Action when I think a partial view should be able to function as a view as well as a partial view.
First note that I am not referring to any specific framework or technology like XAML.
The question is how to implement the MvvM pattern using ICommand for selection of an item in a list (=clicking a row)?
I have a view model (pseudo code):
class ListViewModel
{
// Items in the list.
public ObservableCollection<T> Items {};
// Command for item selection.
public ICommand ItemSelectedCommand
{
...
}
// Select an item in the list.
public void SelectItem(int index)
{
...
}
// The current selected item.
public T SelectedItem
{
get { ... };
}
}
How would I now connect my UI to that view model "manually"? Say, for instance in an iOS application.
I would probably have a UITableViewController, get an instance of the view model and populate the UITableView contents from it. Then I would trigger the ICommand from the RowSelected() method.
And here comes the thing I don't understand: how does the view model now know which item index was selected? I don't want to call SelectItem() because then I would not need the loosely coupled ICommand at all.
And maybe here we have to look how it is solved in XAML to understand the trick?
Coming from XAML and WPF, there are two options to forward selection changes from the UI to the ViewModel (as I understand your question, you're not asking about the other way around - feedbacking changes in the ViewModel to the UI - here):
Command with payload
The ICommands Execute method has a payload parameter. Executing a command without a payload can be done passing null:
SomeCommand.Execute(null);
In your case, it would make sense to pass the selected item as the parameter in the event handler:
vm.ItemSelectedCommand.Execute(eventArgs.SelectedItem);
or
vm.ItemSelectedCommand.Execute(myList.SelectedItem);
In the command's execution method, you can handle the parameter. Note that your ViewModel property SelectedItem is not directly involved here. If you need the selected index explicitly (which is not the case, usually), I would check the selected item's index in the Items collection.
Binding selected item of list to a ViewModel property
Option B is to 'bind' the selected item of the list to a distinct property on the ViewModel, in your case the SelectedItem property in the event handler of the list:
vm.SelectedItem = myList.SelectedItem;
The command is kind of redundant then, although you could invoke it without a payload after setting SelectedItem on the ViewModel. I would rather handle the change of the selected item in the set accessor of the property on the ViewModel.
Note: XAML and WPF come with quite a lot of infrastructure code out of the box. MVVM doesn't make sense without a proper framework to actually take care of binding UI and ViewModels in a loosely coupled way. You quickly end up with a lot of extra work and little benefit, because you're still maintaining tight dependencies. Bottom line: I recommend getting or writing a proper MVVM framework, before actually implementing it.