I have a WP7 app I'm creating and I want a login screen to appear if the user hasn't logged in yet. I have Main.xaml which has a view model MainViewModel.cs. For the login or signup portions I have them embedded as a Grid in Main.xaml, but I would think having them as a user control would work fine also. The login and signup portions will have their own view model, possibly the same one for both, AccountViewModel.cs, that the Grid or user control has it's DataContext set to.
After the user signs up or logs in, which occurs in AccountViewModel.cs, what is the best way for MainViewModel.cs or Main.xaml to know that it is complete, and it can begin loading data, or doing whatever it needs to do?
My initial thought is to use MVVM Light's messaging system. After signup/login occurs, broadcast a message that it's complete, and MainViewModel.cs will be registered to the message and can act on it.
Is there another way or more proper way of letting Main know something has occurred in it's child?
If this is too hard to follow I can add code examples.
A messaging system, such as the one in MVVM Light is a great way to decouple these kind of actions and provide notifications in the way you describe. Can't say as I'd advocate anything else really. The Prism library provides an EventAggregator, which does the same thing, but if you're already using MVVM Light, then stick with that.
Another approach would be to store this kind of info (IsLoggedIn) in a "global view model" such as SettingsViewModel.Instance for example. For a viewmodel of global meaning like Settings, it is an approach that makes a lot of sense IMHO. If you make this property raise the PropertyChanged event, this allows you to dynamically modify the UI when the property changes, and hide the login UI smoothly for instance.
cheers,
Laurent
Related
I have login page and I have bind login button to command in view model. I want to navigate from this page to other user control which is Home page.
It is possible to do this using binding between view and view model?
This is a good question. Let us not forget the reason why you use MVVM in the first place. The good thing about MVVM is that you can separate the data that is presented from the presentation code. Hopefully, by doing this, your application is easier to test, and you can slap a different UI on it e.g. WinRT and it will work.
The requirements are:
You show a logon page,
The user types in their credentials,
You navigate to an application page.
However, if you use the NavigationService, then when the user hits the back-button, they will go back to the logon page, which you probably don't want.
In this case, you are better off showing a Popup that overlays the entire application page. Then close the popup when the credentials are verified.
Depending on whether you prefer View-First or ViewModel-First, you'd structure things differently. Here's a ViewModel first approach:
LogonViewModel logon = new LogonViewModel();
logon.LogonSucceeded += () =>
{
App.DismissViewFor<LogonViewModel>(logon);
AppViewModel appViewModel = new AppViewModel();
App.ShowViewFor<AppViewModel>(appViewModel);
}
App.ShowViewFor<LogonViewModel>(logon);
You can either roll your own framework to implement App.DismissViewFor, App.ShowViewFor or use one like Caliburn.Micro which provides a ViewLocator.
My app contains the following moduls:
SystemModel --> SystemViewModel --> SystemWindow
SettingsModel --> SettingsViewModel --> SettingsWindow
My SystemViewModel contain SettingsViewModel and other things.
In my SystemViewModel I create some Instance that its ctor receives SettingsViewModel.
If i want to update the settings I opened new SettingsWindow as ShowDialog with SettingsViewModel as him DataContext. If the user click "ok" I update the settings else I don't update.
My problem is that I dont know how to update the Settings in the Instance that I created in the SystemViewModel (Instance that received SettingsViewModel in his ctor).
Any idea?
Can you create only one instance of settings view model, maybe residing in a common view model that serves kind of a root for the view model and providing the glue that binds the models together?
Something like a view model controller, even if this sound a bit strange. This root view model could react to events from the view models and then can do everything that is required to update the other settings.
Another approach is a messaging based approach like the one that is implemented by MVVM Light Toolit. I have used this once and after the project got rather big this approach was kind of complicated regarding maintenance.
Update:
You can find information about MVVM Light Toolkit here.
I have a silverlight navigation application where I load and initialize a lot of things in the MainPage.aspx loading.
All the Pages (views) are dependent on the loading of that data.
But really often my users add an internet shortcut on their desktop for my application. but the link often points to a specific page like that :
http://myServer/MyApp/default.aspx#/TheView
I want to force the users to go to the "Default" view (and ignore the #/view parameter) when the application Starts up.
Whats the best way I can do that?
I don't think it's a good idea to 'avoid' links. You should construct the application in a way when it's not a problem.
For example you can send a message from your main logic when everything loaded, and until that message you can disable the appropriate UI (while waiting for data). Messenger (or EventAggregator in Prism) is a publisher-subscriber pattern to achive communication between components without reference to each other. If you don't know it yet, take a look at MVVMLight Messenger or Prism EventAggregator
But if the first option is not okay for you, you can play with the Frame control's JournalOwnership property:
http://msdn.microsoft.com/en-us/library/system.windows.controls.frame.journalownership(v=vs.95).aspx
http://msdn.microsoft.com/en-us/library/system.windows.navigation.journalownership(v=vs.95).aspx
OwnsJournal is your value, because it does not integrate with the browser journal and the url stays the original so your users can't bookmark a 'sub page'.
You can also implement your own journal mechanism.
Another :), but pretty ugly option would be if you track the first page load (in OnNavigatedTo Page events for example), and at the very first request you manually navigate to the main page. Or in the App.xaml.cs, when application starts up you forward the page request.
But I recommend the first one.
I have a Silverlight app that is using the MVVM pattern. I have a WCF service which will allow me to authenticate users (I don't have direct control over that service - assume it is a black box that just returns me the user info and a list of privileges the user has). So, when the app starts up, I want to pull security data from that service.
Right now, when I do this, my views and view models can end up getting initialized before the service returns with the security data. This causes problems because the view models need to disable buttons and make things visible/invisible based on the user having certain privileges.
Is there a pattern that allows me to prevent the initialization of the views / view models until the WCF call has returned? How would you go about solving this problem as elegantly as possible?
Generally, you use BusyIndicator from Silverlight Toolkit for scenarios like this one.
Instead of disabling the UI, it shows them a progress instead.
What you do is provide a IsBusy property on ViewModel. While loading data, set it to True and False rest of the time. Wrap your UI with a BusyIndicator control and bind that property's value with BusyIndicator's IsBusy property.
With this in place, your UI will acknowledge whenever it's busy.
I would like log user actions in winforms applications. The "user actions" mean "click to menu item/button", "move/maximize/minimize/close form", "keydown/up", etc...
The log should contains time, action type (click/keydown/etc...), target (name/text of control).
I have access to source code of target application, but I would like to not override methods like "OnClick" or "OnKeyDown" in every winforms control I'm using, if it is not necessary.
Is there some elegant solution, how to do it?
Thanks!
You could use attributes but I wonder if the benefits will outweigh the cost?
See this link for an example of creating an attribute that can be set on each method
http://www.yoda.arachsys.com/csharp/benchmark.html