Сообщения с тегами относительные ссылки

Относительная гиперссылки с Silverlight навигации

Если вы еще не заметили уже, я случайно, как функция Навигация в Silverlight совсем немного (Интересно, почему? :) ). На мой другие сообщения о судоходстве , я провел некоторое время изучает, как можно перейти на страницы в собраниях, помимо главной сборки приложения и каким образом эти собрания могут быть загружены по требованию "(выдан, он использует некоторые обходные пути, но это заставляет нас, куда мы хотим идти!).

Это все хорошо, но она представляет раздражает проблема, которая влияет на управляемость такого кода. В частности, она заставляет каждый гиперссылки внутри каждого из внешних сборок знать, как относятся к его сборки по имени (это похоже на проблемы с абсолютным URL-адреса в гиперссылки на веб-страницах - эти связи стали тесно связан с страницы, для которой они были созданы, и не могут быть скопированы на другие проекты).

Технически, почти все Юрис, используемые навигационной рамки сегодня относительной Юрис (если UriMappings используются, чтобы включить в абсолютных относительных), но они зависят от приложения и не относительная Page родственниками. Это означает, что если у вас есть страницы на сайте " / Views/Page1.xaml "и хотите дать ссылку на другую страницу в" / Views/Page2.xaml "в рамках Page1, вы должны ссылаться на весь путь (" / Views/Page2.xaml "), а не только относительный путь на другой странице (например, "Page2.xaml" или "./Page2.xaml").

В этой должности, мы будем смотреть на способ, чтобы Page-относительной навигации в вашем Silverlight страницы. Подхода я буду использовать воспользуются INavigate интерфейс, который был добавлен в Silverlight 3 и контроля HyperlinkButton, который использует этот интерфейс для выполнять навигацию при нажатии.

INavigate интерфейс выглядит следующим образом:

  открытый интерфейс INavigate 
  (
     / / Методы 
      source); Ьоо Navigate (Ури источника);
 ) 

Это простой интерфейс с простой целью: позволить компонента обеспечивают способ справиться навигации Ури. В настоящее время только один компонент, встроенных в Silverlight, что на самом деле использует это контроль HyperlinkButton. Мы используем этот элемент довольно часто в Навигация-приложений, так как позволяет нам оценить особенности управления Frame, чтобы перейти к Page Ури. В рамках проекта Silverlight Навигация Применение шаблонов, вы увидите, XAML следующим образом:

 : Frame x : Name =" ContentFrame " Style ="{ StaticResource ContentFrameStyle }" Source ="/Home" Navigated ="ContentFrame_Navigated" NavigationFailed ="ContentFrame_NavigationFailed"> </ navigation : Frame > <Навигации: Frame х: Name = "ContentFrame" Стиль = "(StaticResource ContentFrameStyle)" Source = "/ Дом" Перемещение = "ContentFrame_Navigated" NavigationFailed = "ContentFrame_NavigationFailed"> </ навигация: Frame> 

И еще:

  x : Name ="Link2" Style ="{ StaticResource LinkStyle }" <HyperlinkButton х: Name = "Link2" Стиль = "(StaticResource LinkStyle)" 
                   TargetName ="ContentFrame " Content ="about"/> NavigateUri = "/ О" TargetName = "ContentFrame" Content = "о" /> 

Это все работает, потому что контроль Frame реализует INavigate. Другими словами, нет никакой магии нет - вы можете использовать это слишком! Вот путь HyperlinkButton работает, когда вы пытаетесь целевой INavigate (примерно :) ):

  • Для каждого родителя FrameworkElement подойдя визуального дерева от HyperlinkButton ...
    • Убедитесь в том, FrameworkElement является INavigate и что его имя совпадает TargetName (игнорируется, если TargetName является недействительным или пустой)
      • Если да, то вызов INavigate.Navigate () на FrameworkElement
      • В противном случае, рекурсивно поиск INavigate это правильно названный в рамках каждого из детей FrameworkElement
    • При отсутствии надлежащим образом имени INavigate было обнаружено, двигаться вверх по визуальному дереву

Иными словами, HyperlinkButton будет искать путь вверх и вниз по визуальному дереву (технически делать предварительный заказ, поиск в ширину от каждого родителя HyperlinkButton, работая свой путь визуального дерева) для соответствующих INavigate позвонить.

Итак, что же все эти вещи INavigate значит для меня?

При том, что технические "детали образом, вопрос, который возникает: как мы можем использовать это, чтобы позволить Page-относительной навигации? Ну, причина навигации Frame работ в рамках Страницы сегодня происходит потому, что контроль Frame реализует INavigate и HyperlinkButton работы ее путь вверх по визуальному дереву, пока не обнаружит этого.

Для наших целей, это замечательно, поскольку это означает, что мы можем перехватить вызов INavigate.Navigate (), реализовав интерфейс где-то между HyperlinkButton и Frame. Там в удобное для этого место, поскольку приложения, которые используют Page / Frame и HyperlinkButtons в рамках этих страниц визуального дерева так:

  • Применение
    • Макет
      • Кадр
        • Страница
          • HyperlinkButton
          • Другие элементы управления
      • Другие управления

Что я предлагаю, что мы Page навигацию осуществлять INavigate и превратить страниц в относительной Ури в приложении относительной Ури, прежде чем передавать их от NavigationService (или Frame) на самом деле выполнять навигацию.

Я пошел вперед и раздвигались DynamicNavigation библиотеку, чтобы осуществлять DynamicPage INavigate делать то, что мы хотим, но вы могли бы сделать то же самое на любой подкласс Page (в том числе все ваши страницы, если вы не хотите общего базового класса) . Вот мой простой реализации (с выключателем для отключения этой функции DynamicPages):

 { return ( bool )GetValue(RelativeLinksProperty); } set { SetValue(RelativeLinksProperty, value ); } } public static readonly DependencyProperty RelativeLinksProperty = DependencyProperty .Register( "RelativeLinks" , typeof ( bool ), typeof ( DynamicPage ), new PropertyMetadata ( true )); private static readonly Uri basePlaceHolderUri = new Uri ( "none:///" , UriKind .Absolute); #region INavigate Members public bool Navigate( Uri navigateUri) { string original = navigateUri.OriginalString; if (RelativeLinks && !navigateUri.IsAbsoluteUri && !original.StartsWith( "/" )) { Uri result; if (NavigationService.CurrentSource.IsAbsoluteUri) { result = new Uri (NavigationService.CurrentSource, navigateUri); } else { Uri baseUri = new Uri (basePlaceHolderUri, NavigationService.CurrentSource); result = new Uri ( "/" + basePlaceHolderUri.MakeRelativeUri( new Uri (baseUri, navigateUri)).OriginalString, UriKind .Relative); } return NavigationService.Navigate(result); } else { return NavigationService.Navigate(navigateUri); } } #endregion риЬИс Ьоо RelativeLinks ((получить возврат (Ьоо) GetValue (RelativeLinksProperty);) множество (SetValue (RelativeLinksProperty, стоимость);)) общественности статической чтения DependencyProperty RelativeLinksProperty = DependencyProperty. Регистрация ("RelativeLinks", ЪуреоЕ (Ьоо), ЪуреоЕ (DynamicPage) новые PropertyMetadata (правда)); частных статических чтения Ури basePlaceHolderUri = новый Ури ("никто не :///", UriKind. Абсолюта); # регионе INavigate Члены общественного Ьоо Navigate (Ури navigateUri) (строки оригинального navigateUri.OriginalString =, если (RelativeLinks и и! navigateUri.IsAbsoluteUri и и! original.StartsWith ("/")) (Ури результате, если (NavigationService.CurrentSource.IsAbsoluteUri) (результат = новый Ури (NavigationService.CurrentSource, navigateUri);) (еще Ури baseUri = новый Ури (basePlaceHolderUri, NavigationService.CurrentSource); результат = новый Ури ("/" + basePlaceHolderUri.MakeRelativeUri (новый Ури (baseUri, navigateUri)). OriginalString, UriKind. Относительная);) возвращение NavigationService.Navigate (результат);) (другое возвращение NavigationService.Navigate (navigateUri);)) # endregion 

Сейчас на странице можно использовать Page относительный Ури на HyperlinkButtons. Все, что вам нужно сделать, это избежать создания TargetName (либо с помощью стиля или непосредственно на HyperlinkButton) и Page будет обрабатывать навигацию!

Page относительный Ури может принимать различные формы. Предполагая, что страница, которую вы в настоящее время является "/ MyLibrary; component/Views/Main/Page1.xaml", следующие преобразования будут происходить (как пример):

  • "Page2.xaml" -> "/ MyLibrary; component/Views/Main/Page2.xaml"
  • "./Page2.xaml" -> "/ MyLibrary; component/Views/Main/Page2.xaml"
  • "../Page3.xaml" -> "/ MyLibrary; component/Views/Page3.xaml"
  • "../Secondary/Page3.xaml" -> "/ MyLibrary; component/Views/Secondary/Page3.xaml"
  • "../../ BasePage.xaml "->" / MyLibrary; компонент / BasePage.xaml "
  • "SubMain/Page4.xaml" -> "/ MyLibrary; component/Views/Main/SubMain/Page4.xaml"
  • "SubMain/Page4.xaml? = B и C = D" -> "/ MyLibrary; component/Views/Main/SubMain/Page4.xaml? = B и C = D"
  • "/ MyLibrary; component/Views/Main/Page5.xaml" -> "/ MyLibrary; component/Views/Main/Page5.xaml" (без изменений)

Cool! Могу ли я увидеть его в действии?

Конечно! :) Как всегда, вы можете играть примерно с запущенным приложением, что делает это здесь:

Live sample of page-relative navigation

Нажмите на ссылку внизу страницы, чтобы peform относительной навигации, которые должны принять Вас в путешествие от количества страниц, - все это перемещения с помощью относительной навигации.

Для сравнения, вот файловую структуру образца приложения.

File structure of the sample application.

Итак, что ваша точка?

Что ж, подведем итог - возможность сделать страниц относительной навигации увеличивает переносимость ваших страниц. Это особенно полезно при использовании его в связке с UriMapping. С техникой выше, "относительная-ности" относится к пользователю перед Ури. Это означает, что вы можете создать UriMappings в целях создания "виртуальных" файловую структуру, и все ваши относительные ссылки должны продолжать работать (и новые может быть возможным!). Дайте ему выстрелили, и дайте мне знать, что Вы думаете! Я продолжаю экспериментировать с Навигация, всегда находится в поиске вещей, которые могли бы улучшить опыт при работе с ним.

Хватит уже! Дайте мне товаров!

Терпение, вы не думаете, что я брошу тебя висит, да? Вот, пожалуйста:

Перестаньте говорить к себе!

Ладно. :)

, , , ,

6 Комментарии