Создание общей, многократно используемой формы XAML для Windows Phone 7 и использование ее из библиотеки классов - PullRequest
1 голос
/ 27 февраля 2011

Хорошо, я новичок в программировании Windows Phone 7 / Silverlight и начал то, что, как я думал, было бы довольно простым процессом, и, к сожалению, столкнулся с (надеюсь!) Маленькой проблемой.

По сути, я пытаюсь создать общую форму XAML, например форму "About.xaml", которая является стандартной для всех приложений в моем наборе приложений. Идея состоит в том, что этот экран «О программе» выглядит одинаково, ведет себя одинаково, единственное отличие состоит в том, что несколько полей (например, имя приложения и т. Д.) Заполняются вызывающим приложением. Кроме того, благодаря общедоступности любые новые функции / исправления / улучшения ошибок полезны для всех приложений (т. Е. Для повторного использования и т. Д.). Сначала я думаю, что эта форма XAML должна «жить» в библиотеке классов, на которую могут ссылаться различные приложения.

Я создал пример решения с двумя проектами, чтобы выделить проблему.

A screenshot of the solution showing the two projects

Прежде всего, я создаю приложение Windows Phone Panorama, которое называется «WindowsPhonePanoramaApplication1». Затем я создаю библиотеку классов Windows Phone, которую я называю «WindowsPhoneClassLibrary1».

В «WindowsPhoneClassLibrary1» я создаю новый класс формы типа «Портретная страница Windows Phone» и называю его «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():

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", откуда запускается приложение.

Я проверил файл XAP, который создается для «WindowsPhonePanoramaApplication1», и, конечно же, он содержит сборку «WindowsPhoneClassLibrary1.dll», содержащуюся в нем. Кроме того, я нашел ссылку в блоге Джеффа Просиза, , в которой описывается способ перехода к форме XAML во внешней сборке в Silverlight 4 (с использованием интерфейса INavigationContentLoader), однако Windows Phone 7 основан на Silverlight 3, и после поиска в документации WP7 этот интерфейс, похоже, не определен. У меня был обзор классов URIMapping / URIMapper, но я не могу найти ничего очевидного, что могло бы заставить NavigationService выглядеть в библиотеке классов.

Вопрос в том, как с помощью Silverlight 3 / Silverlight для Windows Phone 7 как «сообщить» «NavigationService» в «WindowsPhonePanoramaApplication1» для «поиска» в библиотеке классов «WindowsPhoneClassLibrary1» для формы «About.xaml» ? Конечно, должен быть какой-то способ повторного использования форм XAML из библиотеки классов?

Кроме того, если вышеупомянутый подход является просто неправильным способом достижения повторного использования общих форм XAML, я был бы заинтересован в любой помощи / ссылках, которые указали бы мне правильное направление.

Заранее спасибо за любую помощь, будет очень признателен ...

1 Ответ

2 голосов
/ 27 февраля 2011

Нашел решение по этой ссылке , довольно просто, если вы знаете синтаксис: -)

Таким образом, у меня сработало следующее:

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