I am new to windows store application development and currently i am developing a news application and i want to refresh the page to get news updated. i stated developing the default layout which is given to us when starting a project and i am lost with the page dictionary because once the page is created. It gets save so is there a way to refresh a page!!! LoadState method is called when application runs for the first time when refresh is clicked the view get clear but all the data is saved in the dictionary according to my knowledge is there a easy way to clear data inside the groups and recall the methods so that the new data will get filled in.can some one please guide me with the relevant steps
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter);
this.DefaultViewModel["Groups"] = sampleDataGroups;
}
private void refresh(object sender, RoutedEventArgs e)
{
this.DefaultViewModel.Clear();
}
There is no excellent answer to this question. But let me talk you through some concepts. Of course, there is no refresh, and the reason for this is many fold. Refresh might be added to the Frame someday, but it's problematic right now.
Consider a navigation service
A good way to navigate in your app is to offload this work to a NavigationService class. This is a simple class that has (something like) custom GotoAppHub() and GotoItemDetail(Item) methods.
The purpose of these methods is not because navigation is difficult, it is because navigation can be centralized. It can check & create the Frame; rather than leaving this erroneously in App.xaml.cs.
If your view model wants to navigate to a page, it simply calls NavigationService.GotoItemDetail(item); to do it, passing the item. This is smart for a few reasons, let me talk you through them.
The first reason this is smart is because you may not want to navigate at all. In some cases navigation relies on data being loaded or the user having permissions. Using the navigation service lets you centralize both the navigation logic and the tests necessary to validate the action.
The second reason this is smart is it allows you to retain the parameter passed to the navigation request. Remember that the Frame does NOT serialize custom, complex types. As a result, passing item in this case is a bad practice. The navigation service can persist this parameter somewhere so the target view model can come pick it up. Moreover, it can persist it for your Refresh().
Consider a static repository class
When a view model is loaded, it should be unnecessary for it to know what previous view model caused it to load. Instead the view model should know what it is supposed to do. And to do its work, it needs data. Every view model can use the repository class to ask for the "current" record. That current record will be set by the navigation service when navigation occurs. In addition, the repository class knows what to do when there is no current record, fetching it should it need.
In addition to holding a reference to the current record, the repository class also understands persistence. What I mean is, when the app is loaded, it knows how to fill the lists. When the app is suspended, it knows how to save the data to a file or web service, or whatever you use. The view model, as a result, does not know this and is, as a result, simpler and easier to maintain.
Consider the Reload() method
It is in the navigation service where you need the reload method. Even more than that, it is only in the navigation service where the reload method can be most effective since the navigation service knows the current type and the current parameter value. The navigation service can store these values in local fields and the reload method can simple repeat the navigation.
Remember the back stack, however. This is like a browser's navigation and repeating the navigation will mean that the same page will exist twice and the GoBack() method you also have in your navigation service will not go back until you go back twice. The solution is simple, just remember to remove with Services.NavigationService.Instance.Frame.BackStack.Remove().
Remember the cost of loading
Sometimes when a page loads there is a considerable cost in loading the UI. This is because whatever you are doing isn't trivial. Calling the Reload() will cause the load of the page to repeat. This is a cost you simply cannot overcome. But, there might be dependencies on the loading of the page that should be bypassed. For example, you might initiate a web service operation when the page is loaded - and that operation should not be repeated. This is up to you to retain a static Boolean that indicates the page has already loaded. But it's important you do not forget it.
One more benefit of the repository
A few paragraphs above I mentioned that your navigation service is the one that can remember the last passed parameter for the reload method to work. If you have an internal rule that only the navigation service can write to the concurrency class then your navigation service doesn't really have to remember. It just has to remember the last navigated-to type. That's because the concurrency class will already have the reference to the item passed in. This is, however, not always useful. Sometimes reload is called to throw away the current changes, which means the current item needs to be reloaded or current changes must be flushed. This will all have to be custom, but I would feel bad if I didn't at least mention it.
Conclusion
This should only be taken as a recommendation. Having said that, I have described here the bulk of large, successful WPF and Windows apps in the marketplace. Using the MVVP pattern, the service pattern for navigation, the repository pattern for concurrency - it's all pretty well proven. But you are the developer. In the end, you should choose what is best.
If you don't like any of that, you can do this:
public bool Reload()
{
if (!this.Frame.BackStack.Any())
return false;
var current = this.Frame.BackStack.First();
this.Frame.BackStack.Remove(current);
return this.Frame.Navigate(current.SourcePageType, current.Parameter);
}
Best of luck!
How about:
private string parameter;
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
parameter = (string)navigationParameter;
reloadData();
}
private void reloadData()
{
var sampleDataGroups = SampleDataSource.GetGroups(parameter);
this.DefaultViewModel["Groups"] = sampleDataGroups;
}
private void refresh(object sender, RoutedEventArgs e)
{
reloadData()
}
Related
I've been giving this some thought lately and I was hoping someone who has better knowledge of MvvmCross than myself can shed some light on this. Given the nuances between each mobile platform there are probably a few different factors that can affect this problem. But for this scenario let's assume we want the best approach for a cross platform solution.
So let's say we have a basic View and a ViewModel class setup. Here's an iOS example.
View
public partial class FirstView : MvxViewController<FirstViewModel>
{
public FirstView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
Request = new MvxViewModelInstanceRequest(FirstViewModel.NewInstance());
base.ViewDidLoad();
}
}
View Model
public class FirstViewModel : MvxViewModel
{
public static FirstViewModel NewInstance()
{
return Mvx.IocConstruct<FirstViewModel>();
}
public FirstViewModel()
{
}
}
Now at the loading of this View or at some point just before the view is created we want to fetch some data from the web using a service that we inject using dependency injection; because the displaying of the view depends on that data. Here lies the problem.. at which point from a platform perspective and in the MvvmCross lifecycle would be the most appropriate place to call the web fetch function in the service.
With regards to platform I would assume that we should do it once the view loads. Because if the fetched data is anything other than simple data types it will be inconvenient to work with on Android, as one would have to persist the data to disk and retrieve it after the navigation, due to serialization between activities.
So assuming we called the web fetch during the view loading process. Where is the best place in the MvvmCross architecture to fire it off, that most closely follows the design paradigms. e.g. The View Model. Is there any lifecycle methods that someone could recommend to call it inside as well. Something like the Start method, called after the view model has been created.
First of all, I don't understand why you won't let the platform itself instantiate and do it's ViewModel lifecycle instead of creating a new instance of the ViewModel using Mvx.IocConstruct. That method does not invoke the ViewModel lifecycle and will not call neither Init or Start on the ViewModel.
If you let the platform do this for you, first the Init method will be called with the arguments that you set when using ShowViewModel<T>(args).
When ViewDidLoad invokes the Start method will subsequently be called.
This gives you two places to invoke the Service that you inject in the ctor of the ViewModel.
If you want more control over when to download the data, you could create some ICommand's, which you invoke on your ViewModel in any of the ViewController lifecycle methods. This could be in the ViewWillDisappear/ViewDidDisappear method, or you could fetch the data.
There are so many ways you can do this. In the end it is entirely up to you, and you can't possibly know when a user decides to change to another View. However, you can make qualified guesses and try fetch data before the user actually wants it.
There is a nice article for you to read here, by Rob Gibbens on how you could do Resilient network services. It describes how you could speculatively fetch resources based on what the user is doing, and this way have something ready for the user to see when he enters the View. This could be cached data or fresh data that you are fetching after showing the cached version.
In any case, I would suggest you stop loading your ViewModel's with Mvx.IocConstruct and let MvvmCross handle this for you in order to get lifecycle methods invoked.
I'm going to ftech list of my application admins(users with role 'admin') and store them in a List<ApplicationUser> AdminList inside a controller of a custom model and in its create action. AdminList is populated inside create action to populate a drop-down in create view.
I want to know is it possible that the list i.e. AdminList will be disposed among calling create and its postback? In other words, is it required to populate AdminList again inside postback method or dispose will never happen?
HTTP is stateless.
Unlike things like WPF applications or Winfows Forms applications, web applications don't maintain a "running application" filled with in-memory state. (At least not in the same intuitive way.) Each request builds up a new state each time. This includes, in the case of MVC, a new instance of the Controller. (Or in the case of Web Forms, a new instance of the Page.)
In order for the data to be persisted from one request to another, you'd need to persist it somewhere. "Somewhere" could be a whole host of different places. The page's form elements, cookies, session, static variables, a database, a file, etc.
For example, if this "admin list" is relatively static and unlikely to change, and is the same for all users of the site, then you might store it in a static property which gets lazy-loaded if it's not set. Something structurally like this:
private static List<ApplicationUser> _adminList;
private static List<ApplicationUser> AdminList
{
get
{
if (_adminList == null)
_adminList = GetAdminsFromData();
return _adminList;
}
}
(However you populate the list would be what that function call does, of course.)
That way the consuming code never really needs to know or care if the list has been populated or not. Just consume the AdminList property and, if it hasn't been populated (if for whatever reason the static context has been cleared, such as an application re-start) then it'll be populated. Otherwise it'll just contain whatever was last put there.
I know there's a lot of questions on the topic and I understand how to do it but I need some help on the design of my architecture. I'm using the Simple MVVM Toolkit.
Architecture
I have a ShellVM which is the main VM for my app. It dishes out navigation and props that my main view binds to.
Then I have a ManageVM that does all the grit work for managing the client, stores, imports, exports etc. It also handles navigation of all my management views.
Then I have an ImportVM that fleshes out the importing of data.
I also have a static PageValues dictionary that stores pages and specific properties and values that should be retained when switching views. It also stores any 'global' properties that is used throughout certain VMs.
I'm using Messaging to pass data between the VMs. The validation and prompts (using dialogs) of the PageValues data is controlled in my ManageVM. I placed it here as I feel my ManageVM should handle all 'management' like setting the client and store. Setting the actual values is done by sending a message to the ShellVM that handles this.
The ShellVM handles the CRUD of the PageValues. So in other words, if any VM gets or sets a global/shell-wide property, it does so by means of messaging to the ShellVM. The ShellVM then sends the message/result back to whichever VM requested it.
Question
This feels very spaghetti-like. I've got a ManageVM that does the loading and validations on PageValues that are actually CRUD'ed in the ShellVM.
Am I on the right track or is there any other suggestion I can try to make this feel a bit cleaner?
Thanks for reading.
Edit
What I'm trying to achieve is to have a container that holds values (ie client and store) that could be accessible from multiple VMs. A bonus is to have each page's/view's values in this container too. Then on showing of the view, it will grab its values from the container and populate the view.
You said
if any VM gets or sets a global/shell-wide property, it does so by
means of messaging to the ShellVM
I propose an interface based approach instead of message passing for this purpose. ViewModels passing messages is for view models to communicate,not for setting a global state. If there is a global state of the application,it is better handled through a dedicated service, IMO.
public interface IApplicationService
{
//your applcation methods here
}
public class ApplicationService:IApplicationService
{
}
public class ManageVM
{
public ManageVM(IApplicationService){}
}
public class ShellVM
{
public ShellVM(IApplicationService){}
}
public class SomeOtherVM
{
public SomeOtherVM(IApplicationService){}
}
Yes, this does sound rather messy. You need to try and isolate areas of functionality into their own VMs so they are not dependent on one another.
One of the tricks I use to do this is to try and imagine that I suddenly need to copy a blob of functionality (say one of your pageviews) into another application. How easy would it be? Would it be a case of just copying one VM and injecting a few dependencies? Or is the VM impossibly coupled to the rest of the app?
It's a bit difficult to give advice without knowing exactly what your app is doing, but really you want each PageVM to be in charge of it's own validation, and CRUD. Or, if the data is shared between many pages, then you need to pass in some kind of repository than the PageVMs can query for data. If validation logic is specific to some data, then put it on the model itself and just leave the presentation of that validation to the VM.
For global settings, I tend to pass around a settings object rather than using messaging.
Have a read up on inversion of control, and dependency injection. These can help you to keep objects loosely coupled because you can see exactly what other things your object is depending upon by looking at the constructor. If you are passing in half the application then it can serve as a warning alarm to try and reduce the coupling.
If I have an aggregate root which consists of say:
class Parent
{
IEnumerable<Child> Children{ get; set; }
}
Children could contain any number of possible Child objects which are stored in the database.
What would be the best way of getting a total list of all Child objects to the application, so they can be presented in a UI allowing a user to attach/remove them from the Parent object?
Having a method in Parent such as
class Parent
{
IEnumerable<Children> GetAllChildObjects { get; set; }
}
would surely corrupt the model with implementation details?
Would it be ok to have a domain service which calls the Parent repository and retrieves a full list. The facade to the application could then call the service directly, ensuring the Parent model stays "pure".
Update:
To give a bit more detail, i'm tidying up a system and trying to give it some structure.
A User can hold a number of WorkLocations. WorkLocations are pretty simple. The current system contains a webpage which displays user details including a full list of valid WorkLocations. Selecting locations from the list updates the User model with the new locations.
Currently, the UI pretty much hits the DB and pulls out the full list of WorkLocations. I need to pull this back into a more structured form.
Or, does this suggest that WorkLocation should not be in the User root as it currently is?
Am I correct in thinking that you want all the WorkLocations from the database, regardless of what User they are attached to (if any)?
If so I would definitely go for the service approach, something like:
public interface IWorkLocationsService
{
IEnumerable<WorkLocation> GetAllWorkLocations();
}
You might want WorkLocation to be immutable so that all changes to them go through User, though I suspect this isn't necessary here.
Update:
You could then add the following methods to User
// This gets filled from the db somehow.
private IList<WorkLocation> workLocations;
// IEnumerable so that all external additions and
// removals must go through dedicated methods.
public IEnumerable<WorkLocation> WorkLocations
{
get { return workLocations; }
}
public void AddWorkLocation(WorkLocation locationToAdd)
{
workLocations.Add(locationToAdd);
// Do whatever else you need to, i.e. mark the item for saving.
}
public void RemoveWorkLocation(WorkLocation locationToRemove)
{
workLocations.Remove(locationToRemove);
// Do whatever else you need to, i.e. mark the item for saving.
}
If you really must get the list of SonOfFoo for some reason, by using simple high level interfaces such as IEnumerable, you're not corrupting the model with implementation details.
Depending on what you need done, it would be better to avoid getting a list of SonOfFoo though, having Foo manage the work would be better.
Also depending on the amount of details SonOfFoo has, it would be a good idea to encapsulate it on an interface with the methods that the UI/Facade would need to use.
Edit:
From your description, the UI needs a list of the WorkLocations a user can work at (a IEnumarable would be a good choice), and then after the user selects the location and confirms it, the UI notifies the control the switch of the user with the selected location.
I have my web application. I need, when a user do a request (I mean, call a page) create an object that store some information (it get these from database) for each request (so the data is updated at every request) and for each user (so UserA don't share the same object regard UserB).
I use to work on Java and some Web Frameworks (like Struts, Spring and JSF) and there was possible to create these objects (JavaBeans) with scope of request, and putting them visible for the whole application. I mean :
public class iContext
{
public iContext()
{
Response.Write(myBeans.Title());
}
}
it's possible without create an Istance of MyBeans every time .
I thought to put the object on session, but I prefeer to get rid about this (in fact I should check, replace, delete or insert the object every time and done tons of queries :)).
Are there some strategies to do this kind of work on .NET 3.5 and C#?
In ASP.Net it's important to know the page's life cycle. If you understand this, you could use the HttpContext.Items[] Dictionary object to fill with your custom context class in the (pre) init phase of the page. Anywhere you load data that's important to keep in memory you can add it to your context class and use it anywhere you want since HttpContext is available at all times in the scope of your page.