开发者

Creating a generic, re-usable, Windows Phone 7 XAML form, and using it from a class library

Ok, so I'm newish to Windows Phone 7/Silverlight programming, and started what I thought would be a fairly straightfoward process, and have unfortunately run into a (hopefully!) small issue.

Basically, I'm trying to create a generic XAML form, e.g., an "About.xaml" form which is standard to all applications in my application suite. The idea is that this "About" screen looks the same, behaves the same, only difference being a few fields (e.g., application name etc) which are populated by the calling application. Plus, because it's shared, any new features/bug fixes/enhancements benefit all apps (i.e., re-use etc). My initial thoughts are that this XAML form should 'live' in a class library, which can be referenced by the various applications.

I've created a sample solution with two projects to highlight the problem.

Creating a generic, re-usable, Windows Phone 7 XAML form, and using it from a class library

First off, I create a Windows Phone Panorama Application, called it "WindowsPhonePanoramaApplication1". Next, I create a Windows Phone Class Library, which I call "WindowsPhoneClassLibrary1".

In "WindowsPhoneClassLibrary1", I create a new form class of type "Windows Phone Portrait Page", and call it "About.xaml".

To recreate the problem, I picked any event, e.g., the "SelectionChanged" event for the list box on the first page of the Panorama (any old event will do, just need a means of calling "NavigationService.Navigate(...))

    <!--Panorama item one-->
    <controls:PanoramaItem Header="first item">
        <!--Double line list with text wrapping-->
        <ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="ListBox_SelectionChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17" Width="432">
                        <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                        <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </controls:PanoramaItem>

In the code behind, I have the following code for the SelectionChanged event:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    NavigationService.Navigate(new Uri("/AboutPage.xaml", UriKind.RelativeOrAbsolute));
}

When I run the application and click on any of the items in the listbox, the method RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) is called, and the application stops at the Debugger.Break() line:

Creating a generic, re-usable, Windows Phone 7 XAML form, and using it from a class library

In the NavigationFailedEventArgs parameter, looking at the Exception object in there, the following error is shown:

{"No XAML was found at the location '/AboutPage.xaml'."}
    [System.InvalidOperationException]: {"No XAML was found at the location '/AboutPage.xaml'."}
    _data: null
    _HResult: -2146233079
    _innerException: null
    _message: "No XAML was found at the location '/AboutPage.xaml'."
    _methodDescs: {System.IntPtr[16]}
    _optionalData: null
    Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146233079
    InnerException: Could not evaluate expression
    Message: "No XAML was found at the location '/AboutPage.xaml'."
    StackTrace: "   at System.Windows.Navigation.PageResourceContentLoader.EndLoad(IAsyncResult asyncResult)\r\n   at System.Windows.Navigation.NavigationService.ContentLoader_BeginLoad_Callback(IAsyncResult result)\r\n   at System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(AsyncCallback userCallback, PageResourceContentLoaderAsyncResult result)\r\n   at System.Windows.Navigation.PageResourceContentLoader.<>c__DisplayClass4.<BeginLoad>b__0(Object args)\r\n   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)\r\n   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)\r\n   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)\r\n   at System.Del
egate.DynamicInvokeOne(Object[] args)\r\n   at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)\r\n   at System.Delegate.DynamicInvoke(Object[] args)\r\n   at System.Windows.Threading.DispatcherOperation.Invoke()\r\n   at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)\r\n   at System.Windows.Threading.Dispatcher.OnInvoke(Object context)\r\n   at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)\r\n   at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)\r\n   at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)\r\n"

I'm pretty certain the reason I get this error is because the "About.xaml" 'lives' in the class library "WindowsPhoneClassLibrary1", and not "WindowsPhonePanoramaApplication1" where the application is running from.

I have checked the XAP file that gets created for "WindowsPhonePanoramaApplication1", and sure enough it has the assembly "WindowsPhoneClassLibrary1.dll" contained within it. Also, I found a link on Jeff Prosise's blog, which highlights a way to navigate to a XAML form in an external assembly in Silverlight 4 (using the INavigationContentLoader interface), however Windows Phone 7 is based on Silverlight 3, and from searching the WP7 documentation, it doesn't appear to have that interface defined. I have had a browse of the URIMapping/URIMapper classes, but can't find anything obvious that would make the Navi开发者_JAVA百科gationService look in the class library.

The question is, using Silverlight 3/Silverlight for Windows Phone 7, how do I 'tell' the "NavigationService" in "WindowsPhonePanoramaApplication1" to 'look in' the class library "WindowsPhoneClassLibrary1" for the "About.xaml" form? Surely, there must be some way of re-using XAML forms from a class library?

Also, if the above approach is simply the wrong way of going about achieving re-use of generic XAML forms, I'd be interested in any help/links that would point me in the right direction.

Thanks in advance for any help, it would be much appreciated...


Found the solution at this link, quite simple if you know the syntax :-)

In summary, the following worked for me:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    NavigationService.Navigate(new Uri("/WindowsPhoneClassLibrary1;component/AboutPage.xaml", UriKind.Relative));
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜