11

In the context of a navigation-style WPF application (NavigationWindow, not XBAP):

Is it possible for a Hyperlink's NavigateUri to contain extra parameters, like path data or a querystring? E.g., is there some way I could set my NavigateUri to /Product.xaml/123 or /Product.xaml?id=123, and have my Product.xaml page be able to see that it was called with a parameter of 123?

Joe White
  • 94,807
  • 60
  • 220
  • 330

3 Answers3

18

You can do this. See http://www.paulstovell.com/wpf-navigation:

Although it's not obvious, you can pass query string data to a page, and extract it from the path. For example, your hyperlink could pass a value in the URI:

<TextBlock>
    <Hyperlink NavigateUri="Page2.xaml?Message=Hello">Go to page 2</Hyperlink>
</TextBlock>

When the page is loaded, it can extract the parameters via NavigationService.CurrentSource, which returns a Uri object. It can then examine the Uri to pull apart the values. However, I strongly recommend against this approach except in the most dire of circumstances.

A much better approach involves using the overload for NavigationService.Navigate that takes an object for the parameter. You can initialize the object yourself, for example:

Customer selectedCustomer = (Customer)listBox.SelectedItem;
this.NavigationService.Navigate(new CustomerDetailsPage(selectedCustomer));

This assumes the page constructor receives a Customer object as a parameter. This allows you to pass much richer information between pages, and without having to parse strings.

Paul Stovell
  • 32,377
  • 16
  • 80
  • 108
  • Where does your NavigationService call belong? In the click handler of the Hyperlink? That seems like it would lead to a lot of extra wiring in the code behind. – dthrasher May 07 '10 at 15:54
  • Yes, in the same way that in ASP.NET MVC the code to render a hyperlink goes in the view, not the model/controller. Navigation from view to view should be a view concern. – Paul Stovell Jan 04 '12 at 13:24
  • In a way it looks like ASP.NET MVC: the "hyperlink" will be on the view, but it will call something to perform the page change. I created a controller to do that, with static methods and a static 'MainWindow' object, which contains the frame that displays all my pages. If I want to change the page, I simply call 'MainController.ChangePage(page)' and it works. – Bruno Machado - vargero Jan 27 '12 at 03:12
  • note that the official MSDN documentation suggests passing parameters in the URL: http://msdn.microsoft.com/en-us/library/ff626521(v=vs.92).aspx; also, the Naviagte method does not seem to take a page as argument, but only an URI object – seb May 28 '12 at 03:52
0

Another way is to create a public variable on the destiny page and use a get/set property to assign a value to it.

On Page:

private Int32 pMyVar;

public Int32 MyVar
{
   get { return this.pMyVar; }
   set { this.pMyVar = value; }
}

When navigating to it:

MyPagePath.PageName NewPage = new MyPagePath.PageName();
NewPage.MyVar = 10;

this.MainFrameName.NavigationService.Navigate(NewPage);

When NewPage is loaded, the integer MyVar will be equal to 10. MainFrameName is the frame you are using in case you are working with frame, but if not, the navigate command remains the same regardless. Its my opinion, but it seems easier to track it that way, and more user friendly to those who came from C# before WPF.

ShadowKras
  • 333
  • 4
  • 14
0
Customer selectedCustomer = (Customer)listBox.SelectedItem; 
this.NavigationService.Navigate(new CustomerDetailsPage(selectedCustomer)); 

Paul Stovell I think that using your suggestion will make your pages not garbage collected because the whole instance will remain on Journal.

wchargin
  • 15,589
  • 12
  • 71
  • 110
  • The first suggestion will enable collection. The second suggestion can still be collected if you call NavigationService.RemoveBackEntry enough times to 'clear' the journal. WPF Frame definitely sucks for this though: http://www.paulstovell.com/magellan-page-management – Paul Stovell Jan 04 '12 at 13:21