Out-of-Browser Silverlight and many "pages" - silverlight

I'm building a Silverlight out-of-browser app that will eventually run on a Windows 7 touchscreen tablet, independent of any browser - it will run just like any other app.
My code, at the moment, is all within one XAML and corresponding .cs file but this is messy and I'd like to split it out and call each page as and when required i.e. Main.xaml, AboutUs.xaml, Contact.xaml etc.
Is this possible in an OOB app? I tried to use the frame and pages controls, but when I set the source to one of my new XAMLs via a button click i.e. "/AboutUs.xaml", it tells me that it's an invalid URI.
Thanks,
Greg.

Try and create a root canvas (e.g: myCanvas) in your MainPage.xaml to act as a container which displays all your pages.
On navigation clicks, write this.
myCanvas.Children.Clear();
myCanvas.Children.Add(new myPage());
A good practice is to set a public property on every page
public MainPage parentPage;
in this case, to which you can assign the parent page that hold that root canvas (myCanvas in case). On further pages, you just navigate using
parentPage.myCanvas.Clear();
anotherPage tempPage = new anotherPage();
tempPage.parentPage = parentPage;
parentPage.myCanvas.Add(tempPage);

Related

WPF fail. Using a WPF page as an instance

Think about a WPF program that has 2 pages which you navigate between. (Upload and Crop)
In the first page, you load an image using a button, select the image, and your image appears in the WPF Image control. Then, you press the "Crop" button. That sends the navigation to the second page, which you can crop the image.
Then, you crop the image in the second page. Then you press "next". Next button must redirect you to the first page, but wait a minute, the image you loaded no longer exist in the page. Because it's a new page.
Dim CropPage As New Crop(Crop_Bmp, Crop_BmpSource)
Me.NavigationService.Navigate(CropPage)
You may think it's okay. Because we pass the parameters and we can refill the WPF Image controls using that parameters. But, there is actually 8 upload panels in the page 1. So, other ones are important.
Or think about another method I found. Instead of using a new page instance, navigate back that you used.
Upload.Crop_Bmp = Crop_Bmp
Upload.Crop_BmpSource = Crop_BmpSource
Me.NavigationService.GoBack()
Upload.Crop()
But in the second one, it throws errors.
"Reference to a non-shared member requires an object reference."
Then, back to the Upload page, I made the variables and functions "Shared". But then, more problems come up. Because you cannot edit the local variables unless you also make them Shared. So, all of the variables and functions need to be "Shared".
I'm searching about a solution for a few days and I could not get rid of them. What method should I use? Redirecting back, or opening a new instance?
In old-type applications, it was very easy. All was that:
Form1.Crop_Bmp = Crop_Bmp
Me.Hide()
Form1.Crop()
And it was working perfectly. Because the forms were not instances like WPF pages. That's the reason I find WPF quite weird.
I found it a way to do this. When navigating to the Crop page, I sent the Upload page as a parameter to Crop Page.
Dim CropPage As New Crop(Crop_Bmp, Crop_BmpSource, Me)
Me.NavigationService.Navigate(CropPage)
Then, in Crop:
Public Sub New(ByVal Crop_Bitmap_ As Bitmap, ByVal Crop_BitmapSource_ As BitmapSource, ByVal pg As Upload)
' This call is required by the designer.
InitializeComponent()
UploadPage = pg
Then, in the Crop page, I accessed that parameter to modify its elements. For example:
Me.NavigationService.Navigate(UploadPage)
UploadPage.Crop()
This sounds like a bad use-case for the Pages metaphor. Pages are for loosely coupled peer screens (E.G. A separate page for each department), but you are using them in a tightly coupled parent-child relationship. (The "Crop" page is the child of the "Upload" page) For what you are doing, launching the crop screen as modal dialog might be more fitting.
If you want to keep everything in the same window, you can keep both functions in the same window, and toggle their visibility as needed.

How to make WPF page navigation code look better?

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/

WPF root element is not valid for navigation

I am converting a WPF XBAP app to a WPF desktop app. I have it running on the desktop, but am now trying to change the Page references to Window references.
'MyApp.StartForm' root element is not valid for navigation.
I have tried creating a simple version of this app and converting that, and this works fine, so there must be something within the XAML that is causing this when using Window tags. My question relates to how I can investigate this. Currently, all I get is this error, accompanied by a "No Source Available" screen; no stack locations are shown and "Show Disassembly" doesn't work. Other than systematically commenting out individual chunks of XAML until it works, is there a way to work out what this issue is?
Navigation in a WPF application can only be done between pages. The error shows up because you're trying to "navigate" to what is now a Window, and this isn't possible.
Instead of converting your Page into a Window, create a new Window with a Frame control in it. A Frame can be used to host your existing pages - which should stay exactly as they are, and not be changed into Windows.
Its not entirely accurate about it not being possible to host a window in a frame, the following code will do it for you
public void HostWindowInFrame(Frame fraContainer, Window win) {
object tmp = win.Content;
win.Content = null;
fraContainer.Content = new ContentControl() { Content = tmp };
}
please check StartForm having the page as root element or some other else. I am having the same. I have check the page which has to be navigated. I declare that page as window.

Creating Pages or Windows 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();

How to set the Image / Icon on a WPF Page

I need to know how to set the very top left icon / image on a WPF page. I know how to do it in a WPF Window the page looks to be different.
Thanks,
Darren
I don't think there's any support for changing the host window's icon based on its current page in a navigation-style application.
One workaround might be to introduce a property of type Image into your pages (perhaps derive all your pages from a base page, or introduce an IHasIcon interface and implement that), then bind the host window's icon to that. Something along the lines of:
<Window ...
Icon="{Binding Content.Icon,ElementName=frame1>
<Frame x:Name="frame1" ... />
</Window>
I haven't tried this but I've done similar things with binding a TextBlock to the "title" of the current page in a navigation application.
It is possible to modify the icon of the host window by adding the following (VB) code to the Loaded event of the page (I didn't test placing the code in the constructor).
Dim hostWindow As NavigationWindow =
DirectCast(
DirectCast(Me.VisualParent,
System.Windows.Controls.ContentPresenter).
TemplatedParent,
System.Windows.Navigation.NavigationWindow)
Dim iconUri As New Uri("MyIcon.ico", UriKind.RelativeOrAbsolute)
hostWindow.Icon = BitmapFrame.Create(iconUri)
Are you referring to a WPF application deployed as an XBAP, if so the same rules apply as a normal website and you would just place a favicon.ico in the root of your IIS website.
http://en.wikipedia.org/wiki/Favicon

Resources