Posts Tagged collegamenti relativi

collegamenti ipertestuali relativi alla navigazione Silverlight

Se non avete già notato, mi capita di come la funzione di navigazione in Silverlight un bel po '(mi chiedo perché? :) ). In my altri post sulla navigazione , ho trascorso un certo tempo esplorare come potrai navigare all'interno di pagine in insiemi diversi da dell'assemblea ricorso principale e di come queste assemblee possono essere caricati on-demand (concessi, si utilizza alcune soluzioni alternative, ma si siamo dove vogliamo andare!).

Questo è tutto bene e buono, but presenta un problema fastidioso che l'impatto della manutenibilità di code such. In particolare, è forces every collegamento ipertestuale all'interno di ciascuna delle assemblee external per sapere come fare riferimento al suo assembly di nome (questa è simile al problema con URL assoluti in collegamenti ipertestuali alle pagine web - i link diventano strettamente accoppiati alla pagina per la quale sono stati creati, e non possono essere copiati in altri progetti).

Tecnicamente, quasi tutti gli URI utilizzato dal quadro di navigazione oggi sono gli URI relativi (a meno che UriMappings sono usati per trasformare quelle in assoluto quelle relative), ma sono relative application-and mai Page-relative. Questo significa che se si ha una pagina at " / Views/Page1.xaml "e desidera creare il collegamento a un'altra pagina a" / Views/Page2.xaml «dal di dentro Page1, si deve fare riferimento l'intero percorso (" / Views/Page2.xaml ") piuttosto che solo il percorso relativo alla pagina (ad esempio "Page2.xaml" o "./Page2.xaml").

In questo post, vedremo at un modo per consentire la navigazione Page-within tuo parente Pagine Silverlight. The approach I will useremo approfittare della interfaccia INavigate aggiunta in Silverlight 3 and control il HyperlinkButton che utilizza questa interfaccia per effettuare la navigazione quando cliccato.

L'interfaccia INavigate assomiglia a questo:

  public interface INavigate 
  (
     / / Metodi 
      source); Naviga bool (Uri fonte);
 ) 

Si tratta di una semplice interfaccia con uno scopo molto semplice: consentire a un componente di fornire un modo per gestire la navigazione a un URI. Al momento, l'unico componente integrato in Silverlight che ha effettivamente vantaggio di esso è il controllo HyperlinkButton. Usiamo questo controllo molto spesso in Navigazione applicazioni abilitate, in quanto ci permette di indirizzare uno particolare controllo Frame per passare a una pagina da Uri. In the progetto Silverlight Navigation modello Applicazione, vedrai XAML like questo:

  : Frame x : Name =" ContentFrame " Style ="{ StaticResource ContentFrameStyle }" <Navigazione: Telaio x: Name = "ContentFrame" style = "(StaticResource ContentFrameStyle)" 
                    Navigated ="ContentFrame_Navigated" NavigationFailed ="ContentFrame_NavigationFailed"> Source = "/ home" navigato = "ContentFrame_Navigated" NavigationFailed = "ContentFrame_NavigationFailed"> 
  : Frame > </ Navigazione: Frame> 

E ancora:

 x : Name ="Link2" Style ="{ StaticResource LinkStyle }" NavigateUri ="/About" TargetName ="ContentFrame " Content ="about"/> <HyperlinkButton x: Name = "Link2" style = "(StaticResource LinkStyle)" NavigateUri = "/ A proposito di" TargetName = "ContentFrame" content = "su" /> 

Tutto questo funziona perché il controllo Frame implementa INavigate. In altre parole, non c'è nessuna magia là - lo si può utilizzare anche! Ecco il modo in cui HyperlinkButton funziona quando si sta cercando di indirizzare un INavigate (circa :) ):

  • Per ogni genitore FrameworkElement risalendo l'albero visuale dal HyperlinkButton ...
    • Verificare se il FrameworkElement è un INavigate e che il suo nome corrisponde TargetName (ignorato se TargetName è null o vuoto)
      • Se è così, chiamata INavigate.Navigate () sul FrameworkElement
      • In caso contrario, ricorsivamente ricerca di un INavigate che è propriamente chiamato all'interno di ciascuno dei figli della FrameworkElement
    • Se non propriamente chiamato INavigate è stato trovato, continuare a muoversi l'albero visuale

In altre parole, il HyperlinkButton cercherà la sua strada su e giù per l'albero di visuale (tecnicamente fare una ricerca pre-ordine in ampiezza da ciascun genitore del HyperlinkButton, facendo strada l'albero visuale) per un adeguato INavigate chiamare.

Allora, cosa fa tutta questa roba INavigate significa per me?

Con tale dettaglio tecnico fuori del modo, la domanda che si pone è: come possiamo usare questa opzione per consentire la navigazione Page-parente? Beh, la navigazione a causa di un frame all'interno di pagine di lavori oggi è perché il controllo Frame implementa INavigate, e la HyperlinkButton si sta facendo strada l'albero visuale finché non trova ciò.

Per i nostri scopi, questo è grande, perché significa che possiamo intercettare la chiamata a INavigate.Navigate () implementando l'interfaccia in qualche luogo fra la HyperlinkButton e la cornice. C'è un posto comodo per questo, dal momento che le applicazioni che utilizzano Page / Frame e HyperlinkButtons all'interno di tali pagine sono un albero visuale come questo:

  • Applicazione
    • Disposizione
      • Telaio
        • Pagina
          • HyperlinkButton
          • Altri controlli
      • Altri controlli

Quello che sto suggerendo è che la pagina si naviga per attuare INavigate e girare pagina, parente di Uri in applicazioni relative Uri prima di consegnare loro fuori del NavigationService (o la cornice) per eseguire di fatto la navigazione.

Sono andato avanti e ampliato la mia libreria DynamicNavigation fare DynamicPage attuare INavigate di fare ciò che vogliamo, ma si potrebbe fare lo stesso su qualsiasi sottoclasse di Page (compresi tutti una delle pagine se non si vuole una classe base comune) . Ecco il mio semplice implementazione (con un interruttore per disattivare questa funzione 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 pubblico RelativeLinks bool (get (return (bool) GetValue (RelativeLinksProperty);) set (SetValue (RelativeLinksProperty, valore);)) public static readonly DependencyProperty RelativeLinksProperty = DependencyProperty. Register ("RelativeLinks", typeof (bool), typeof (DynamicPage) , nuovo PropertyMetadata (true)); private readonly static Uri basePlaceHolderUri = new Uri (":///" nessuno, UriKind. assoluto); # regione INavigate membri pubblici bool Navigate (Uri navigateUri) (stringa = navigateUri.OriginalString originale, se (RelativeLinks & &! navigateUri.IsAbsoluteUri & &! original.StartsWith ("/")) (risultato Uri, se (NavigationService.CurrentSource.IsAbsoluteUri) (risultato = new Uri (NavigationService.CurrentSource, navigateUri);) else (baseUri Uri = new Uri (basePlaceHolderUri, NavigationService.CurrentSource); risultato = new Uri ("/" + basePlaceHolderUri.MakeRelativeUri (nuovo Uri (baseUri, navigateUri)). OriginalString, UriKind. Relative);) ritorno NavigationService.Navigate (risultato);) else ( ritorno NavigationService.Navigate (navigateUri);)) # endregion 

Ora, all'interno the pagina, si can utilizzare Page-URI relativo's on HyperlinkButtons. All devi fare avoid is setting uno TargetName (sia attraverso uno style o direttamente sul HyperlinkButton), e la pagina handle la navigation!

Page-URI relativo può assumere varie forme. Presumendo che la pagina che stai attualmente è "/ MyLibrary," component/Views/Main/Page1.xaml, le seguenti trasformazioni si verifichi (come esempio):

  • "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; componente / BasePage.xaml "
  • "SubMain/Page4.xaml" -> "/ MyLibrary; component/Views/Main/SubMain/Page4.xaml"
  • "SubMain/Page4.xaml? A = b = c & d" -> "/ MyLibrary; component/Views/Main/SubMain/Page4.xaml? A = b = c & d"
  • "/ MyLibrary; component/Views/Main/Page5.xaml" -> "/ MyLibrary; component/Views/Main/Page5.xaml" (nessun cambiamento)

Cool! Posso vederlo in azione?

Certo! :) Come sempre, si può giocare con una applicazione in esecuzione che fa questo qui:

Live sample of page-relative navigation

Clicca sul link in fondo a questa pagina, per una navigazione peform relativo che si dovrebbe prendere in un viaggio tra un numero di pagine - che navigare utilizzando la navigazione relativo.

Per riferimento, qui è la struttura dei file per l'applicazione di esempio.

File structure of the sample application.

Allora, qual è il tuo punto?

Bene, per riassumere - in grado di fare aumenti di navigazione pagina relativa alla portabilità delle pagine. E 'particolarmente utile se lo si utilizza in combinazione con UriMapping. Con la tecnica di cui sopra, la "parente-ness" si riferisce per l'utente- di fronte Uri. Ciò significa che è possibile creare UriMappings al fine di creare una struttura "virtuale di file e tutti i link relativi dovrebbe continuare a lavorare (e di quelli nuovi potrebbe essere possibile!). Dategli un colpo e fatemi sapere cosa pensate! sto continuando a sperimentare con navigazione, sempre alla ricerca di cose che potrebbero migliorare l'esperienza di quando si lavora con esso.

Basta! 'Dammi la merce!

Pazienza! Non hai davvero che ti avrei lasciato appeso, vero? Ecco qua:

Smettila di parlare a voi stessi!

Okay. :)

, , , ,

6 Commenti