reference the component using the xaml file - wpf

I would like to act on the View from my ViewModelClass by code, not just modifying the properties, to which the XAML binds to.
member x.SelectedUdl
with get() = selectedudl
and set value = selectedudl <- value
//do fancy things like
//this.Quotes12.ItemsSource <- asyncquotes.gethisto (undls |> Seq.head, 2012)
However to do this, I need a reference to the component itself.
Do I have any way to add a reference to "this" from the xaml or other way ?
<UserControl.DataContext>
<ViewModel:QuotesViewModel>
<x:Arguments>
THIS
</x:Arguments>
</ViewModel:QuotesViewModel>
</UserControl.DataContext>
<DockPanel>
type QuotesViewModel(this:Window) =
inherit ViewModelBase()
Edit
I finally added a Global.fs file, in the first position so that it is acessible for all compilation units
module Global
open FSharpx
type MainWindow = XAML<"MainWindow.xaml">
type Singleton private () =
static let instance = Singleton()
let mutable ivalue : MainWindow = null
static member Instance = instance
member this.Value
with get () = ivalue
and set value = ivalue <- value
let window () = Singleton.Instance.Value
Note that it uses the XAML type provider, so you have to move the FMVVM template MainWindow's Frame up a level to benefit from strong type access.
Then in the View, you can add
Global.window().TextBox.Text <- "hello"
With this, we can use both the declarative way, or the code approach, in a strongly typed way.
Initialisation is easily done
let mainWindow = MainWindow()
Global.Singleton.Instance.Value <- mainWindow
// Application Entry point
[<STAThread>]
[<EntryPoint>]
let main(_) =(new Application()).Run(mainWindow.Root)
(recommendations welcome, I am just starting to look at wpf..)

Related

Closing a dialog with FSharp.ViewModule

In my previous question "Enabling dialog OK button with FSharp.ViewModule", I got to the point where a dialog's OK button was enabled only when the validators for the dialog's fields were true, and ViewModule's IsValid property became true. But I ran into a couple more problems after that:
1) Clicking on the OK button didn't close the dialog, even if I set IsDefault="true" in XAML.
2) When the OK button is clicked, sometimes I want to do more checks than provided by the ViewModule validators (eg, checking an email address). Then I want to stop the dialog from closing if this custom validation fails.
But I don't know how to do both when using F# and MVVM. First I tried putting the XAML into a C# project and the view model code in an F# library. And then I used the OK button's Click handler in code behind to close the window. This fixed 1), but not 2).
So this is my XAML:
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="OK" IsEnabled="{Binding IsValid}" IsDefault="true" Command="{Binding OkCommand}"
<!--Click="OnOK"--> />
And my view model - with a comment in the validate function to show what I want to do when the OK button is clicked:
let name = self.Factory.Backing( <# self.Name #>, "", notNullOrWhitespace)
let email = self.Factory.Backing( <# self.Email #>, "", notNullOrWhitespace)
let dialogResult = self.Factory.Backing( <# self.DialogResult #>, false )
let isValidEmail (e:string) = e.Length >= 5
member self.Name
with get() = name.Value
and set value = name.Value <- value
member self.Email
with get() = email.Value
and set value = email.Value <- value
member self.DialogResult
with get() = dialogResult.Value
and set value = dialogResult.Value <- value
member self.OkCommand = self.Factory.CommandSync(fun () ->
if not <| isValidEmail(email.Value) then
MessageBox.Show("Invalid Email") |> ignore
else
dialogResult.Value <- true
)
It's worth pointing out that MVVM and code-behind aren't best friends.
The C# event handler you're referring to is located in the Window's code-behind file (i.e. partial class). Although code-behind is considered ok for view related logic, it's frowned upon by MVVM purists. So instead of specifying event handlers in XAML, MVVM prefers the use of Commands.
Option A - Doing it in code-behind, being pragmatic.
Note that FsXaml doesn't provide direct wiring of events (specifying handlers in XAML), but you can wire up the events yourself in code-behind.
After you name a control in XAML, you can get a hold on it in the corresponding source file.
UserDialog.xaml
<Button x:Name="butt" ... >
UserDialog.xaml.fs
namespace Views
open FsXaml
type UserDialogBase = XAML<"UserDialog.xaml">
type UserDialog() as dlg =
inherit UserDialogBase()
do dlg.butt.Click.Add( fun _ -> dlg.DialogResult <- System.Nullable(true) )
Validation is best handled in the ViewModel, e.g. using custom validation for the email adress:
SimpleMVVMDemo
FSharp.ViewModule.Validation.Validators.custom
Option B - You can follow MVVM pattern using a DialogCloser.
First add a new source file at the top of your solution (Solution Explorer)
DialogCloser.fs
namespace Views
open System.Windows
type DialogCloser() =
static let dialogResultProperty =
DependencyProperty.RegisterAttached("DialogResult",
typeof<bool>, typeof<DialogCloser>,
new PropertyMetadata(DialogCloser.DialogResultChanged))
static member SetDialogResult (a:DependencyObject) (value:string) =
a.SetValue(dialogResultProperty, value)
static member DialogResultChanged
(a:DependencyObject) (e:DependencyPropertyChangedEventArgs) =
match a with
| :? Window as window
-> window.DialogResult <- System.Nullable (e.NewValue :?> bool)
| _ -> failwith "Not a Window"
Say our solution is called WpfApp (referenced in XAML header), we can then implement the DialogCloser like this:
UserDialog.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Views;assembly=WpfApp"
xmlns:fsxaml="http://github.com/fsprojects/FsXaml"
views:DialogCloser.DialogResult="{Binding DialogResult}"
>
...
</Window>
Now in the UserDialog's ViewModel you can hook up a Command and close the dialog by setting the dialogResult to true.
member __.OkCommand = __.Factory.CommandSync(fun () ->
if not <| isValidEmail(email.Value) then
System.Windows.MessageBox.Show ("...") |> ignore
else
// do stuff (e.g. saving data)
...
// Terminator
dialogResult.Value <- true
)
You could also skip the if / else clause and validate the email using custom validation.
To wrap it up, you can call the dialog from MainViewModel using this helper function:
UserDialog.xaml.fs
namespace Views
open FsXaml
type UserDialog = XAML<"UserDialog.xaml">
module UserDialogHandling =
/// Show dialog and return result
let getResult() =
let win = UserDialog()
match win.ShowDialog() with
| nullable when nullable.HasValue
-> nullable.Value
| _ -> false
Note that there's no 'code-behind' in this case (no code within the UserDialog type declaration).

Code behind WPF and F#

Is it possible to make an application in F# that uses WPF with a classic code behind? I know it works perfect with MVVM and no code behind, but I need to implement an interface on a UserControl. Is that possible with F#?
To help a bit, here is the code I want to translate from C# to F#
public class Test : UserControl, IContent {
public void InitializeComponents() {
// Do the initialization magic
}
public Test() {
}
public void OnFragmentNavigation(FragmentNavigationEventArgs e) {
this.DataContext = new { description = "Hallo Welt :)" };
}
public void OnNavigatedFrom(NavigationEventArgs e) {
}
public void OnNavigatedTo(NavigationEventArgs e){
}
public void OnNavigatingFrom(NavigatingCancelEventArgs e) {
}
}
And this is the markup
<UserControl xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Test">
<TextBlock Text="{Binding description}"></TextBlock>
</UserControl>
It really depends on what you mean by "classic code behind". As mentioned by Petr, F# does not have partial classes (and there is also no editor support), so you won't get the same experience (when you are accessing elements or adding events). But you can certainly build a WPF application that uses the same programming model.
One way to get something that is very close to standard code behind is to define a class, associated with each xaml file, that looks something like this:
type SomeComponent() =
let uri = System.Uri("/AppName;component/SomeComponent.xaml", UriKind.Relative)
let ctl = Application.LoadComponent(uri) :?> UserControl
let (?) (this : Control) (prop : string) : 'T =
this.FindName(prop) :?> 'T
let okBtn : Button = ctl?OkButton
do okBtn.Click.Add(fun _ -> (* .. whatever *) )
This loads the XAML content and then uses the dynamic lookup operator to find all the UI elements (which you'd get for free in C#). A nicer F# solution is to use FsXaml, which has a XAML type provider (but sadly, not much documentation).
I found a solution, I just make it short, here is the code:
namespace Testns
open System.Windows.Controls
open FirstFloor.ModernUI.Windows
open Microsoft.FSharp.Core
open System
type TestUserControl() =
inherit UserControl()
interface IContent with
member x.OnFragmentNavigation(e: Navigation.FragmentNavigationEventArgs): unit =
let vm = ViewModel("Hallo Welt :)")
base.DataContext <- vm
()
member x.OnNavigatedFrom(e: Navigation.NavigationEventArgs): unit = ()
member x.OnNavigatedTo(e: Navigation.NavigationEventArgs): unit = ()
member x.OnNavigatingFrom(e: Navigation.NavigatingCancelEventArgs): unit = ()
And the markup
<local:TestUserControl xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Testns;assembly=App">
<TextBlock Text="{Binding description}"></TextBlock>
</local:TestUserControl>
This is not the answer for the actual question, it just works for my use case. So feel free to answer it :)
Probably no. As far as I know F# doesn't support partial classes.
But you can use F# XAML type provider as described here: http://www.mindscapehq.com/blog/index.php/2012/04/29/using-wpf-elements-from-f/

Can I implement my own view resolution service and have RequestNavigate use it?

I 'm fairly new to Prism and I 'm currently re-writing one of our existing applications using Prism as a proof of concept project.
The application uses MVVM with a ViewModel first approach: our ViewModel is resolved by the container, and an IViewResolver service figures out what view it should be wired up to (using name conventions amongst other things).
The code (to add a view to a tab control) at the moment looks something like this:
var vm = (get ViewModel from somewhere)
IRegion reg = _regionManager.Regions["MainRegion"];
var vw = _viewResolver.FromViewModel(vm); // Spins up a view and sets its DataContext
reg.Add(vw);
reg.Activate(vw);
This all works fine, however I 'd really like to use the Prism navigation framework to do all this stuff for me so that I can do something like this:
_regionManager.RequestNavigate(
"MainRegion",
new Uri("NameOfMyViewModel", UriKind.Relative)
);
and have Prism spin up the ViewModel + View, set up the DataContext and insert the view into the region.
I 've had some success by creating DataTemplates referencing the ViewModel types, e.g.:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Module01">
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestView />
</DataTemplate>
</ResourceDictionary>
...and have the module add the relevant resource dictionary into the applications resources when the module is initialized, but that seems a bit rubbish.
Is there a way to effectively take over view creation from Prism, so that when RequestNavigate is called I can look at the supplied Uri and spin up the view / viewmodel based on that? There’s an overload of RegionManager.RegisterViewWithRegion that takes a delegate that allows you to supply a view yourself, and I guess I’m after something like that.
I think I might need to supply my own IRegionBehaviorFactory, but am unsure what's involved (or even if I am on the right path!).
Any help appreciated!
--
note: Originally posted over at the prism codeplex site
Sure you can do that. I 've found that Prism v4 is really extensible, if only you know where to plug in.
In this case, you want your own custom implementation of IRegionNavigationContentLoader.
Here's how to set things up in your bootstrapper (the example is from a subclass of UnityBootstrapper from one of my own projects):
protected override void ConfigureContainer()
{
// IMPORTANT: Due to the inner workings of UnityBootstrapper, accessing
// ServiceLocator.Current here will throw an exception!
// If you want access to IServiceLocator, resolve it from the container directly.
base.ConfigureContainer();
// Set up our own content loader, passing it a reference to the service locator
// (it will need this to resolve ViewModels from the container automatically)
this.Container.RegisterInstance<IRegionNavigationContentLoader>(
new ViewModelContentLoader(this.Container.Resolve<IServiceLocator>()));
}
The ViewModelContentLoader itself derives from RegionNavigationContentLoader to reuse code, and will look something like this:
public class ViewModelContentLoader : RegionNavigationContentLoader
{
private readonly IServiceLocator serviceLocator;
public ViewModelContentLoader(IServiceLocator serviceLocator)
: base(serviceLocator)
{
this.serviceLocator = serviceLocator;
}
// THIS IS CALLED WHEN A NEW VIEW NEEDS TO BE CREATED
// TO SATISFY A NAVIGATION REQUEST
protected override object CreateNewRegionItem(string candidateTargetContract)
{
// candidateTargetContract is e.g. "NameOfMyViewModel"
// Just a suggestion, plug in your own resolution code as you see fit
var viewModelType = this.GetTypeFromName(candidateTargetContract);
var viewModel = this.serviceLocator.GetInstance(viewModelType);
// get ref to viewResolver somehow -- perhaps from the container?
var view = _viewResolver.FromViewModel(vm);
return view;
}
// THIS IS CALLED TO DETERMINE IF THERE IS ANY EXISTING VIEW
// THAT CAN SATISFY A NAVIGATION REQUEST
protected override IEnumerable<object>
GetCandidatesFromRegion(IRegion region, string candidateNavigationContract)
{
if (region == null) {
throw new ArgumentNullException("region");
}
// Just a suggestion, plug in your own resolution code as you see fit
var viewModelType = this.GetTypeFromName(candidateNavigationContract);
return region.Views.Where(v =>
ViewHasDataContract((FrameworkElement)v, viewModelType) ||
string.Equals(v.GetType().Name, candidateNavigationContract, StringComparison.Ordinal) ||
string.Equals(v.GetType().FullName, candidateNavigationContract, StringComparison.Ordinal));
}
// USED IN MY IMPLEMENTATION OF GetCandidatesFromRegion
private static bool
ViewHasDataContract(FrameworkElement view, Type viewModelType)
{
var dataContextType = view.DataContext.GetType();
return viewModelType.IsInterface
? dataContextType.Implements(viewModelType)
: dataContextType == viewModelType
|| dataContextType.GetAncestors().Any(t => t == viewModelType);
}
// USED TO MAP STRINGS OF VIEWMODEL TYPE NAMES TO ACTUAL TYPES
private Type GetTypeFromName(string typeName)
{
// here you need to map the string type to a Type object, e.g.
// "NameOfMyViewModel" => typeof(NameOfMyViewModel)
return typeof(NameOfMyViewModel); // hardcoded for simplicity
}
}
To stop some confusion about "ViewModel first approach":
You use more a "controller approach", but no "ViewModel first approach". A "ViewModel first approach" is, when you inject your View in your ViewModel, but you wire up both, your ViewModel and View, through a third party component (a controller), what by the way is the (I dont want to say "best", but) most loosely coupled approach.
But to answer your Question:
A possible solution is to write an Extension for the Prism RegionManager that does exactly what you have described above:
public static class RegionManagerExtensions
{
public static void AddToRegion<TViewModel>(
this IRegionManager regionManager, string region)
{
var viewModel = ServiceLocator.Current.GetInstance<TViewModel>();
FrameworkElement view;
// Get View depending on your conventions
if (view == null) throw new NullReferenceException("View not found.");
view.DataContext = viewModel;
regionManager.AddToRegion(region, view);
regionManager.Regions[region].Activate(view);
}
}
then you can call this method like this:
regionManager.AddToRegion<IMyViewModel>("MyRegion");

F#/WPF event binding

I am wandering if there is a way of hooking an event defined in XAML to a F# function of member ? Of course, I could do it diagrammatically but it is kind of inconvenient.
I suppose the question is whether you can specify F# member as an event handler using XAML markup:
<Button x:Name="btnClick" Content="Click!" Click="button1_Click" />
As far as I know, the answer is No.
The way this works in C# is that the registration of event handler is done in C# code (partial class) generated by the designer (you can see that in the obj directory in files named e.g. MainForm.g.cs). F# doesn't have any direct support for WPF designer, so it cannot generate this for you. You'll have to write the code to attach event handlers by hand (but that's quite easy).
I have some examples in my London talk about Silverlight. You can implement the ? operator to get nice access to the XAML elements:
type MainPage() as this =
inherit UserControl()
let uri = new System.Uri("/App;component/MainPage.xaml", UriKind.Relative)
do Application.LoadComponent(this, uri)
// Get button using dynamic access and register handler
let btn : Button = this?btnClick
do btnClick.Click.Add(fun _ -> (* ... *))
The ? operator declaration that I used is:
let (?) (this : Control) (prop : string) : 'T = // '
this.FindName(prop) :?> 'T
It is possible to add binding to a command, eg. using the Command="..." property in the button.
So in you XAML you can have:
<Button Command="{Binding MyCommandHandler}">
Then in your ViewModel code, if you have a member called MyCommandHandler, it'll be bound to the above button. So in your F#, something like:
module ViewModel =
type FuncCommand (canExec:(obj -> bool), doExec:(obj -> unit)) =
let theEvent = new DelegateEvent<EventHandler>()
interface ICommand with
[<CLIEvent>]
member x.CanExecuteChanged = theEvent.Publish
member x.CanExecute arg = canExec(arg)
member x.Execute arg = doExec(arg)
type MyViewModel() =
member this.MyCommandHandler =
new FuncCommand(
(fun _ -> ... SOME CODE WHICH RETURNS TRUE OR FALSE ...),
(fun _ -> ... SOME CODE TO HANDLE THE CLICK ...)
)
You can do it using an attached property:
namespace Foo
open System.Windows
open System.Windows.Controls
open System.Windows.Controls.Primitives
open System.Windows.Media
module Register =
// http://stackoverflow.com/a/14706890/1069200
type internal Marker = interface end
let ClickHandlerProperty = DependencyProperty.RegisterAttached(
"ClickHandler",
typeof<RoutedEventHandler>,
typeof<Marker>.DeclaringType,
PropertyMetadata(null))
let SetClickHandler (element: UIElement, value : RoutedEventHandler) =
element.SetValue(ClickHandlerProperty, value)
let GetClickHandler (element: UIElement) : RoutedEventHandler =
element.GetValue(ClickHandlerProperty) :?> _
let private OnClick (sender : obj) args =
let button = sender :?> UIElement
let handler = GetClickHandler button
if not (obj.ReferenceEquals(handler, null)) then
handler.Invoke(sender, args)
let private initialize =
EventManager.RegisterClassHandler(
typeof<FrameworkElement>,
ButtonBase.ClickEvent,
RoutedEventHandler(OnClick))
Then use it in xaml like this:
<Window ...
xmlns:foo="clr-namespace:Foo;assembly=Foo">
<Button Content="Click!" foo:Register.ClickHandler="{x:Static foo:Bar.OnClicked}" />
</Window>
Where bar is:
namespace Foo
open System.Windows
module Bar =
let OnClicked =
let onClick _ _ = MessageBox.Show "clicked" |> ignore
RoutedEventHandler(onClick)
I don't know f# so the above code can probably be cleaned up a lot.
For the click event David's suggestion to bind the command is probably nicest.
This is now supported in the newer versions of FsXaml, though it works slightly differently than it does in C#.
Using FsXaml, you can define your Xaml and specify your event handler. For example, in a window named "MyWindow", you can do:
<Button Content="Click!" Click="button1_Click" />
In your "code behind" file, you would handle this like so:
type MyWindowBase = XAML<"MyWindow.xaml">
type MyWindow () =
inherit MyWindowBase
override this.button1_Click (_,_) = () // Handle event here

SIlverlight Navigate: how does it work? How would you implement in f# w/o VS wizards and helpers?

update 5: brians solution worked:
namespace Module1
type Page1() as this =
inherit UserControl()
let uriStr = "/FSSilverlightApp;component/Page1.xaml"
let uri = new System.Uri(uriStr, System.UriKind.Relative)
do
Application.LoadComponent(this, uri)
member public this.Uri with get () = uri
type MyApp() as this =
inherit Application()
do Application.LoadComponent(this, new System.Uri("/FSSilverlightApp;component/App.xaml", System.UriKind.Relative))
let nav : Frame = siteTemplate ? contentFrame
let p1 = new Module1.Page1() ;
member this.navigate ea =
nav.Navigate(p1.Uri)
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Module1.MyApp">
<Application.Resources>
</Application.Resources>
</Application>
<UserControl x:Class="Module1.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="This is page 1 Lets see if we can ever get here!!!" FontSize="24" />
</Grid>
</UserControl>
update 4:
the template Brian has mentioned is mostly doing the trick. I still have a more complex page that is giving me troubles - yet it is most likely my code. Once my code is complete I will post what I can diagnose but the parts include:
Setting App.XAML correctly (referencing your application object correctly)
in post construction of your application object use Application.Load to load the App.xaml
In your application object create instances of your page xaml
in post construction of your page objects use Application.Load to load the individual page.xaml
each of your page objects should extend UserControl; I suspect this is not truly the case - once I get more more complex page running I will see if removing this restriction will have an effect.
update 3:
I implemented my own controller logic in the Application object, which seems to do part of the trick (and solve my needs for a prototype anyhow).
type Page1() as this =
inherit Page()
do
this.Content <- loadXaml("Page1.xaml")
type MyApp() as this =
inherit Application()
let cc = new ContentControl()
let mainGrid : Grid = loadXaml("MainWindow.xaml")
let siteTemplate : Grid = if mainGrid.Name = "siteTemplate" then mainGrid else mainGrid ? siteTemplate
let nav : Frame = siteTemplate ? contentFrame
let page1 = new Module1.Page1() :> Page ;
let page2 = new Module1.Page2() :> Page ;
let page3 = new Module1.Page3() :> Page ;
do
this.Startup.Add(this.startup)
// to be able to get focus
cc.IsTabStop <- true
cc.IsEnabled <- true
System.Windows.Browser.HtmlPage.Plugin.Focus()
cc.Content <- mainGrid
this.RootVisual <- cc
member this.startup ea =
menu.MenuItemClicked.Add(this.navigate)
resolutionSlider.SizeChanged.Add(this.resizeTemplate)
member this.navigate ea =
if ea.Index = 1 then nav.Content <- page1
elif ea.Index = 2 then nav.Content <- page2
elif ea.Index = 3 then nav.Content <- page3
It works... I don't know the implication on memory / performance. I wonder if the navigation fw handles the construction / destruction of page objects more efficiently than what I did. I think the navigation FW works nicely with the browsers back and forward buttons - which my solution doesn't.
update 2: it looks as though teh C# applciation implments
public void InitializeComponent()
which loads and the XAML. Though I am no IL expert; I will make the similar changes on the F# side... I wonder if it is the partial class concept. One theory I am working on is:
page.xaml.cs is definitely a partial class - you can read it in the source.
page.xaml has an attribute that refers back to the c# class. I wonder if the special build commands treat this as a partial class - by parsing it and creating 1) any member component references 2) intialComponent() method which registers the page wherever it needs to be registered?
Update 1: After a nights sleep the problem can be stated more accurately as I have a 100% f# / silverlight implementation and am looking to use the built in Navigation components. C# creates page.xaml and page.xaml.cs um - ok; but what is the relationship at a fundamental level? How would I go about doing this in f#?
The applcuation is loaded in the default module, and I pull the XAML in and reference it from the application object. Do I need to create instances / references to the pages from within the application object? Or set up some other page management object with the proper name value pairs?
When all the Help of VS is stripped away - what are we left with?
original post (for those who may be reading replies)
I have a 100% silverlight 3.0 / f# 2.0 application I am wrapping my brain around. I have the base application loading correctly - and now I want to add the naigation controls to it.
My page is stored as an embedded resource - but the Frame.Navigate takes a URI. I know what I have is wrong but here it is:
let nav : Frame = mainGrid ? mainFrame
let url = "/page1.xaml"
let uri = new System.Uri(url, System.UriKind.Relative) ;
nav.Navigate uri
Any thoughts?
Have you tried making the Xaml a file in the project with a BuildAction of Content rather than an EmbeddedResource? Honestly, I've no clue if that works, but it might get packaged into the .xap that way, and then the relative uri might work. How would it work in a C# project? Try that.
EDIT
Aha, Dmitry's template appears to have this figured out. He has Xaml files with BuildAction of Resource, and then code like
type MainPage() as this =
inherit UserControl()
do
Application.LoadComponent(this,
new System.Uri("/SilverlightApplication3;component/Page.xaml",
System.UriKind.Relative))
let layoutRoot : Grid = downcast this.FindName("LayoutRoot")
do
()
to load it.

Resources