I'm following a small tutorial on how to switch pages in Silverlight. It can be found here:
http://jesseliberty.com/2008/05/31/multi-page-applications-in-silverlight/
It's slightly older, but everything worked.
The technique used here is to have a seperate page with a "Navigator function". If you're on Page1, you use something like this:
PageSwitcher ps = this.Parent as PageSwitcher;
ps.Navigate(new Page2());
With Navigate being the only function in PageSwitcher:
public void Navigate(UserControl nextPage) {
this.Content = nextPage;
}
Still, the way this is handled seems kind of odd. I'm still wondering what the difference is between adding a new User Control and Page. I've tried adding them both, they very much seem the same.
It seems like this is just using a hidden page to engineer the switching between the public pages. This seems somehow over the top to me. Is there an other way?
I think the difference between Page and UserControl is that Page has some Navigation methods like NavigationService.
For another way, check out Caliburn Micro's Screens and Conductors. It lets you do some advanced navigation stuff with little effort, check out the sample, HelloScreens. It adds life-cycle to your Screens. Also the ability to know when the view's been bound and nice stuff like that.
Related
I'm a fresher with WPF, MVVM. Now, I have been investigating MVVM Light. I got some confused. I appreciate any help from all of you. Thanks in advance for taking a look at this post.
Can we absolutely remove code behind of View (such as: Invoking InitializeComponent() somewhere inside .xaml --> Does not need view.xaml.cs anymore in some simple case).
I have many views insight my project, how many locator is necessary?
I intend to make separate locator for each view. And I wonder that if I register all locators in app.xml, are all of views initialized and registered right after user run the application? If Yes, Is it not good for performance?
Main question:
I have a scenario:
I have many forms: such as :
MainForm: which is the 1st form invoked by application.
ImportForm: which is invoked when User click Import (from MainForm)
Assumption that: I did finish all stuff related to binding (such as button Import --> RelayCommand(OnImport))
What is the best practice for me to implement this scenario?
1. Just implement to init and show ImportForm like below:
public void OnImport()
{
ImportForm importForm = new ImportForm();
importForm.ShowDialog();
}
It's simple, but I wonder if this way follow the MVVM's paradigm?
So, I did some researching and do another way like:
public void OnImport()
{
//// Just send message
Messenger.Default.Send(
new NotificationMessage(this, "OnImport"));
}
In Code Behind: MainForm.xaml.cs
public MainForm()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this, (nm) =>
{
if (nm.Sender == this.DataContext)
{
if (nm.Notification == "OnImport")
{
ImportForm importForm = new ImportForm();
importForm.ShowDialog();
}
}
});
}
By this way, I must write some code inside code behind --> Is it a problem?
Both above solutions can finish mentioned scenario correctly, but I confused which one is better or is there any actually right solution out there?
Thanks again for your patience with the long question.
No, you cannot. InitializeComponent() paints UI on the screen. The purpose of MVVM is to separate logic that does not related to View and store it in a ViewModel. It does not tend or aim to remove code-behind.
It depends on you. You can create one Locator for all ViewModels or one Locator per one ViewModel. Anyway, I found that Locator does not scale well and hard to manage in a larger project. It creates dependency between View, Locators and ViewModels. I personal prefer to use DI framework instead of Locator even if it is a small project.
You can do both, depends on your requirement. (a) If clicking the button on the main form does nothing more than show a dialog then I would use Click event because it is View related. It has nothing to do with any logic, so keep it in the code behind is the best solution for me. (b) By the way, if clicking the button does something, for example, connect to a database then show a dialog if a condition is true. In this case, I would use Messenger to keep View and ViewModel separate from each other.
I want to make a program by WPF which includes several pages.
I have a Window and several Pages now.
In order to navigate, I use
this.Content = new Page1();
in the main window (from Window to Page), and
((Window)this.Parent).Content = new Page1();
between pages (from Page to Page), because Page can only be sub-element of Window or Frame.
However, the second line of code above looks quite ugly.
Is there a better way to achieve the same goal?
I have coded from several Windows Phone applications before, and I think it might be better to navigate between Pages rather than hide/show elements (such as Grids).
If your navigation code is on your Page class, either :
move it to the window class
create an event in the Page class, and react to it on the Window class.
Is there any reason why you can't just put a Frame in your Window ?
You could use NavigationService.
http://msdn.microsoft.com/en-us/library/ms750478.aspx
http://www.paulstovell.com/wpf-navigation
Maybe this could help:
http://azerdark.wordpress.com/2010/04/23/multi-page-application-in-wpf/
I'm new to using WPF. I have the following program I want to create:
-Application opens up with one button
-User clicks button and it takes them to a new page with various input.
I'm confused about how I need to do this. I tried opening a new window, but I don't want a window to open up, I want it to be all one Window. I tried creating a new page and navigating to it using NavigationService but couldn't get it to work.
Basically I want to create a workflow where the user enters some stuff, clicks the next button and is taken to a new page to enter some more information. Can anyone point me in the right direction?
Use Pages in your application and use NavigationService to switch between them.
For example, if you have two pages in your paplication, "Page1" and "Page2" you can include the following in Page1.xaml:
<Button Content="Next" Click="NextClicked" />
and this in your Page1.xaml.cs:
void NextClicked(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Page2());
}
Alternatively you could use this:
NavigationService.Navigate(new Uri("Page2.xaml", UriKind.Relative));
Generally it is easier to do the first, because you can also set properties of Page2. For example, if Page2 has a public "CurrentItem" property you could say:
NavigationService.Navigate(new Page2 { CurrentItem = this.Something });
You can't do that with the Uri-based syntax.
You can also create instances of various pages (Page1, Page2, etc) and store them in your Application object, then switch to them like this:
NavigationService.Navigate(App.Page2);
This way if you ever navigate to Page2 later you will get exactly the same Page2 object. Alternatively you could use NavigationService's Journaling feature to help with this.
Initially there doesn't seem to be much of a difference in the preference of what should be used: Pages or Windows. However, looking at the intended goal of the application, I would suggest using UserControls instead of Pages, as Pages seem to focus on Web related content, though they can be used in stand alone applications as well. Another argument that has been made in another post is referring to the MSDN-documentation, and points out that in using a Page the NavigationWindow that it is hosted in does not remember the instance of the content that is navigated to and thus other WPF-techniques are needed to store that content in your navigation history.
NavigationWindow does not store an instance of a content object in navigation history. Instead, NavigationWindow creates a new instance of the content object each time it is navigated to by using navigation history. This behavior is designed to avoid excessive memory consumption when large numbers and large pieces of content are being navigated to. Consequently, the state of the content is not remembered from one navigation to the next. However, WPF provides several techniques by which you can store a piece of state for a piece of content in navigation history.
If you use a UserControl, you wouldn't have that problem if your goal is to create a native application anyway. You can download this template as an example to use UserControls instead.
The use of the NavigationService is the right way to do that. You have to add a frame to your windows to show your pages, then navigating between them with the NavigationService.
You can change your application object's MainWindow reference to another Window object.
Application.Current.MainWindow = new SecondWindowToBeDisplayed();
I'm starting a new project in Wpf, and am now looking into using Prism. For now I'm simply trying to set up the navigation of the application using Prism. Unfortunately my lack of experience with the framework makes it a bit difficult to get started..
To be more precise about my first challenge I have an application with a "navigation/menu" region and a "main" region. The navigation region will be the same for all different main region views, and I therefore define the menu in the shell.xaml. When clicking any menu item I'd like to add a view to the region using Prism. First; is this something one typically will use Prism for? If so; what's the typical approach? And I mean on a more structural level..
My impression is that Prism will make my application much more scalable in the end, and I see that I get some other advantages from it - like the IoC container. So I would like to use it - if I could only get through the first steps..
I've got a sample that uses a little more of the CAG feel for modules contributing to a menu and how to add views to a region. It ought to make things a little more clear.
http://dl.getdropbox.com/u/376992/CAGMenus.zip
Hope this helps,
Anderson
Bumbuska,
Prism will be a great way for you to achieve this functionality and it is pretty easy to do once you understand the principals.
The way I will do it is to add event listeners in the start up event of your Main Region. When you select your item in the menu, you fire the event. When that happens your Main Region will handle the event and you clear the current view from the Main Region. Then create the new view you want to use and add it.
Your main region should look something like this:
public void Initialize()
{
Events.PageEvents.ClickedEvent1 ce1 = this.eventAggregator.GetEvent<Events.PageEvents.ClickedEvent1>();
ce1.Subscribe(LoadView, ThreadOption.UIThread, true);
}
private void LoadView(Events.HomePageEvents.Clicked clicked1)
{
IRegion mainRegion = RegionManager.Regions["MainRegion"];
foreach (object view in new List<object>mainRegion.Views))
{
RegionManager.Regions["MainRegion"].Remove(view);
}
IModule firstModule = Container.Resolve<Modules.FirstModule>();
firstModuleModules.Initialize();
}
I hope that points you in the right direction. Please let me know if you need any more info.
I am currently loading the default file, page.xaml, but in that page, I am loading the content from another xaml file. With each "page" change, I just load the content from a different xaml file, and on and on.
Example: this.Content = new StartPage();
I'm running into some syntax issues, however, because of the way I am changing my content, and was wondering if there is a definitive answer on how to accomplish this?
For example, when trying to capture user's keystrokes, I would normally do:
this.Keydown += new KeyEventHandler(this_KeyDown);
but that event handler doesn't even fire in my situation. So, I'm looking for a new approach to my content-switching approach before revisiting the keystroke problem.
Have you looked at using Silverlight 3. It has a new Page Navigation functionality.Silverlight 3 Navigation
As far as content switching goes, I've always done what you propose in the question. Normally I create a MainPage.xaml which has has the frame of the application (usually a Grid for me). One of the cells in the Grid is considered the content area of the app. When the user takes an action that I would consider to be navigation, I create a new instance of a Page, which for me is a file like MyUserControl.xaml, and then add it to the appropriate content cell in the Grid. MainPage stays around for the life of the application and assists with navigation.
If you want something fancier, and want to take advantage of browser based back/forward buttons, you could look into the SL3 navigation like Correl suggested.
A Big problem with what your're doing is that journalization doesnt take place automatically when you swap out framework elements by creating them and plugging them in the codebehind. This means that you lose the back and forward functionality of the browser. You can manually journalize stuff when you swap out pages, but this is simply a hack to get your navigation approach working.
Take a look at Prism at www.compositewpf.codeplex.com/, specifically the MVVM method of GUI design, it'll save you alot of time later on. And remember, you dont need to go hardcore when you look at MVVM, u could always cut out alot of "dynamic" functionality if you're a one man band
Also swap to silverlight 3 and use the navigation application. If you cant, take a look at helix 0.3, it'll provide a more asp oriented approach to navigation. the link provides a really really good starting point, its a three part article, i suggest you read all three and download the sample application and understand it.
A book could have been written on your question, this has to suffice for now.