创建通用的、可重用的 Windows Phone 7 XAML 表单,并从类库中使用它
好的,我对 Windows Phone 7/Silverlight 编程很陌生,并开始了我认为相当简单的过程,但不幸的是遇到了一个(希望如此!)小问题。
基本上,我试图创建一个通用的 XAML 表单,例如“About.xaml”表单,它是我的应用程序套件中所有应用程序的标准。这个想法是这个“关于”屏幕看起来相同,行为相同,唯一的区别是由调用应用程序填充的一些字段(例如,应用程序名称等)。另外,因为它是共享的,所以任何新功能/错误修复/增强都会使所有应用程序受益(即重用等)。我最初的想法是,这个 XAML 表单应该“存在”在类库中,可供各种应用程序引用。
我创建了一个包含两个项目的示例解决方案来突出该问题。
首先,我创建一个 Windows Phone 全景应用程序,将其命名为“WindowsPhonePanoramaApplication1”。接下来,我创建一个 Windows Phone 类库,将其称为“WindowsPhoneClassLibrary1”。
在“WindowsPhoneClassLibrary1”中,我创建一个“Windows Phone Portrait Page”类型的新表单类,并将其命名为“About.xaml”。
为了重现问题,我选择了任何事件,例如全景图第一页上列表框的“SelectionChanged”事件(任何旧事件都可以,只需要一种调用“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>
在后面的代码中,我有以下用于 SelectionChanged 事件的代码:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NavigationService.Navigate(new Uri("/AboutPage.xaml", UriKind.RelativeOrAbsolute));
}
当我运行应用程序并单击列表框中的任何项目时,方法 RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
是调用,应用程序停止在 Debugger.Break()
行:
img src="https://i.sstatic.net/0mbsR.png" alt="RootFrame_NavigationFailed method">
< NavigationFailedEventArgs
参数,查看其中的 Exception
对象,显示以下错误:
{"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"
我很确定收到此错误的原因是因为“About.xaml” “生活”在类库“WindowsPhoneClassLibrary1”中,而不是运行应用程序的“WindowsPhonePanoramaApplication1”中,
我检查了为“WindowsPhonePanoramaApplication1”创建的XAP文件,并且果然它包含程序集“WindowsPhoneClassLibrary1.dll”。在其中。另外,我在 Jeff Prosise 的博客上找到了一个链接,突出显示了在 Silverlight 4 中导航到外部程序集中的 XAML 表单的方法(使用 INavigationContentLoader
界面),但是 Windows Phone 7基于Silverlight 3,通过搜索WP7文档,它似乎没有定义该接口。我浏览了 URIMapping/URIMapper 类,但找不到任何明显的东西可以使 NavigationService
在类库中查找。
问题是,使用 Silverlight 3/Silverlight for Windows Phone 7,我如何“告诉”“WindowsPhonePanoramaApplication1”中的“NavigationService”来“查找”类库“WindowsPhoneClassLibrary1”中的“About.xaml”表单?当然,一定有某种方法可以重用类库中的 XAML 表单吗?
另外,如果上述方法只是实现通用 XAML 表单重用的错误方法,那么我会对任何能够为我指明正确方向的帮助/链接感兴趣。
预先感谢您的任何帮助,我们将不胜感激...
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.
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:
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 NavigationService
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...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
找到解决方案在此链接,非常简单如果您知道语法:-)
总之,以下内容对我有用:
Found the solution at this link, quite simple if you know the syntax :-)
In summary, the following worked for me: