On a Frame in silverlight I want to be able to navigate to an existing instance of a Page. In short this is what I want:
Page p = ...; // initialize the page and set some of the properties
contentframe.Navigate(p);
Instead of using an Uri from which the page is created.
Can this be achieved (as in WPF), or should the frame rather be replaced by a ContentControl?
Edit: More clarity: Is there a way that NavigationService.Navigate(object root) that is available in WPF can be simulated in silverlight?
You question seems really quite confused.
should the frame rather be replaced by a ContentControl?
That would imply that you don't have good reason to have the frame there in the first place and you aren't using a navigating framework. In which case certainly you should replace the Frame with something else.
If you can replace the frame with something else the there is no need for your "Page" to be of type Page, it may as well be a UserControl.
It can all boil do down to have this simple Xaml:-
<Border x:Name="content" />
and this cs:-
UserControl p = ...;
content.Child = p;
Edit:
You need to keep the frame therefore you can't replace it with a ContentControl.
You might just assign your Page directly to the Frame Content property. However I'm not sure what would happen if you then click the back button. I suspect it would navigate to the page prior to the page you replaced.
Another option would be to us a static service to push your page properties on to a stack, you page can then pop them off this stack when initialising. This would allow you to navigate using a Uri to your page.
The problem you are facing is the same problem that I am facing. An event happens outside the frame, and the page has no idea that the event has ocured, but it needs to be notified of that event.
Now what can be done is force the page within that frame to refresh itself or handle those events by 1: storing the page's state temporarily, and b) passing "commands" through the query string.
Related
I have one ListView and ContentFrame (Frame Control) inside of my MainPage.xaml.
For example if I Navigate page Content.xaml to this ContentFrame and then I need to call Navigate from his Content.xaml. But Navigate have to change content of main application Frame (it is parental Frame).
How can I do this?
Keep a reference to your root frame somewhere - e.g. as a static property on the App class and use that to call Navigate(). Alternatively you can walk up the visual or perhaps also logical tree and find the next frame to get the reference.
I need to build some kind of phone emulator to test our webservice and have a general idea how the flow will go.
Doesn't needs to be anything fancy.
Now I made a WPF form with a phone image in it. In the display of the phone I have placed a frame. That looks good so far :)
But what now? How can I fill the frame with say the startscreen? Do I need to create a usercontrol for each page I want to view or show? Or is there another approach?
And how about databinding? I want to use MVVM, so I need to create a viewmodel for each usercontrol like we do normally? Or a viewmodel for each page?
I just discovered the WPF Frame Control and it seems there's not so much info on the net to find, or not what I want.
Thx for any pointers in the right direction.
Here is an image how it now looks:
For each view (screen) that the end user is going to see you will need to make a page that will hold all your logic and functions per page. All you do in Cycle through the pages in your own way.
FrameName.Navigate(PageName);
Remember to initialize the pages before you can use them. You can intialize them when you use the Navigate function like:
FrameName.Navigate(new PageName());
This works well for smaller projets, bigger projects you might want to use some clever way of initializing the pages because you navigate, like:
if(TimeToLoadPage == True)
{
PageName pagename = new PageName();
RunPageNavigation()
}
public Void RunPageNavigation()
{
FrameName.Navigate(pagename);
}
You can data bind the width and height of the page by inheriting from the Frame (Going through Ancestry route). You can do all the content based stuff in a page exactly the same as a window. You can't however control the page like a window.
Hope this helps a bit more.
I have a problem with Bing Maps control I use in my WP7 application.
When I'm navigated to the page with map control, it starts the GeoCoordinateWatcher. When GeoCoordinateWatcher has some location data for me, it calls a SetView() method to center the map at current location. There is also a button on ApplicationBar that's also starting the GeoCoordinateWatcher.
Now, the thing is, when I first navigate to this page, all works fine: GeoCoordinateWatcher starts, gives me the location data after some time, calls SetView() and the map centers when I need it too. The same with the button.
But if I press the Back button to get back to the main page and then try to navigate again to the map page, SetView() stops working. In debugging I see that the code surrounding it works as expected and the data passed to SetView() is correct, but nothing happens with the control and events for changing view don't fire either.
I'm assuming there may be something wrong with map initialization (or disposing on navigating from), but I don't know where to dig.
Edit:
I've tried changing Map.Center directly and it doesn't work in exactly the same way the SetView() doesn't: it works fine the first time page is navigated to and doesn't work on the other times.
Edit 2:
Ok, it gets weirder. In debugging I see that my map's center actually gets set to a correct value. But an actual control shows absolutely different location and me, moving map around, doesn't change the value that I see from code.
Edit 3:
I've added a button to ApplicationBar that just calls SetView() and it works fine. Apparently, the problem appears when I call SetView() as a result of GeoCoordinateWatcher.PositionChanged event raising. How could I work around that?
Try using map.Center = loc.CoOrdinates;
I've found the solution.
In my original code I've subscribed to the GeoCoordinateWatcher.Position property change event in the page constructor: App.PropertyChanged += AtmInfoPageOnAppPropertyChanged
All I had to do was to move that to the OnNavigatedTo event handler and add App.PropertyChanged -= AtmInfoPageOnAppPropertyChanged to the OnNavigatedFrom event handler.
I think, the problem was that keeping the old page subscribed to the event didn't allow it to be disposed, and at the same time didn't allow the new page to subscribe to that same event, thus causing the code to be called for the different page and different map control than the one displayed on the screen.
I have a page with multiple update panels, each containing dynamically created User Controls that contain a button control.
When The button in a control is clicked the control no longer exists in the page load event and so the click event of the button within the control cannot be raised.
To get round this I am currently recreating ALL the controls on the page in each page load event, but this is obviously causing a lot of unneccesary page updating. In any given partial postback, the only control(s) that need to be recreated are the ones in the update panel containing the control that has been clicked.
How then can I best identify which control has been clicked in page_load and then only recreate the controls in the relevant update panel to be able top then access the click event of that control?
I know I can do the following
if (ScriptManager1.IsInAsyncPostBack)
{
string clickedControlId = ScriptManager1.AsyncPostBackSourceElementID
}
But this isnt hugely useful as knowing the ID of the control doesnt neccesarily help me identify which Update Panel it belonged to. Is there a way of adding a command argument to the control when it is created at run time and reading that command argument in the page load event during the partial postback?
If not, any other suggestions?
Many thanks
Stewart
1) Stop using update panels they add an unnecessary level of complexity that creates more problems than is worth, especially when you have more than one in a page.
2) Stay away from mixing Ajax functionality with server-side logic. You will end up writing a lot of code to compensate one or the other.
What I suggest:
Don’t use update panels!
Keep the code that generates the initial page load. Instead of posting to the server with a .Net button, use a regular button and use the onClick=”foobar_ajax(id, ….Update UI)” to make an ajax call to update the data on the server. Include the ID of the item(the control) you are clicking on. When your ajax call is done you may not need to do anything or you could update the UI with some new data from the server (I recommend refreshing after saving).
Read: Calling the page method with jQuery instead.
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
I use a page (named containerpage) with a ContentPresenter (named PageContent) and set its content to a PhoneApplicationPage instance (contentpage) in the page's OnNavigatedTo() eventhandler. I also have a mainpage with a button "Show Form". When I click on that button, the program navigates to the containerpage, that sets its contentpresenter's content to the contentpage. My problem is: if I click on "show form", then press the back button and click on "show form" again, I get ArgumentException with the text
"The parameter is incorrect"
on line
this.PageContent.Content = contentpage;
in the containerpage's OnNavigatedTo() eventhandler. I guess this is because I already set another ContentPresenter's Content to this contentpage (because navigating creates a new page), but if this is the problem, how can I unassign my contentpage from the previous ContentPresenter's Content?
As decyclone mentioned, your question would be a lot clearer with detailed code. That said, you might implement OnNavigatedFrom() on your conatinerpage and set the Content to null.
You might want to consider how this design holds up if the app gets tombstoned on containerpage.
To be honest, I'm amazed that setting the Content property of one page to be an instance of another page even works! I really would advise against that as a long term solution. If the content of the first page is dynamic based on some condition, then use different UserControls instead.
If the data for the UserControl is not persistent between calls to ShowForm, then you can just create a new instance each time and then you won't have the re-parenting problem.
If you can elaborate on your application scenario and what you are trying to achieve, then we might be able to provide a better answer.