2011-01-28 27 views
7

Voglio avere una risorsa stringa, che contiene un collegamento ipertestuale. Credo che questo non è possibile, a meno che non ho avuto 4 stringhe di risorse:WPF Resources.resx stringa con collegamento ipertestuale?

testo pre-collegamento ipertestuale collegamento ipertestuale href testo hyperlink di testo Post-collegamento ipertestuale.

Poi costruirlo nel XAML via:

<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right"> 
    <TextBlock Grid.Column="1" Text="{x:Static p.Resources.PreHText}" /> 
    <Hyperlink Grid.Column="1" NavigateUri="{x:Static p.Resources.HHref}"> 
    <TextBlock Text="{x:Static p.Resources.HText}" /></Hyperlink></TextBlock> 
    <TextBlock Grid.Column="1" Text="{x:Static p.Resource.PostHText}" /> 
</StackPanel> 

Che è semplicemente orribile, per molte diverse ragioni (Styling, non molto dinamico etc etc). Bar che crea il mio rendering e il mio formato di stringa, ad esempio "Invia un'email {[email protected]|the helpdesk} per ulteriore assistenza". C'è un altro modo per raggiungere questo obiettivo? (Non è necessario utilizzare il file Resources.resx)

risposta

1

Alla fine ho appena fatto il mio controllo TextBlock per esso (Imaginitively chiamato AdvancedTextBlock):

public class AdvancedTextBlock : TextBlock { 
     new private String Text { get; set; } //prevent text from being set as overrides all I do here. 
     private String _FormattedText = String.Empty; 
     public String FormattedText { 
      get { return _FormattedText; } 
      set { _FormattedText = value; AssignInlines(); } 
     } 
     private static Regex TagRegex = new Regex(@"\{(?<href>[^\|]+)\|?(?<text>[^}]+)?}", RegexOptions.Compiled); 

     public AdvancedTextBlock() : base() { } 
     public AdvancedTextBlock(System.Windows.Documents.Inline inline) : base(inline) { } 

     public void AssignInlines(){ 
      this.Inlines.Clear(); 
      Collection<Hyperlink> hyperlinks = new Collection<Hyperlink>(); 
      Collection<String> replacements = new Collection<String>(); 
      MatchCollection mcHrefs = TagRegex.Matches(FormattedText); 
      foreach (Match m in mcHrefs) { 
       replacements.Add(m.Value); 
       Hyperlink hp = new Hyperlink(); 
       hp.NavigateUri = new Uri(m.Groups["href"].Value); 
       hp.Inlines.Add(m.Groups["text"].Success ? m.Groups["text"].Value : m.Groups["href"].Value); 
       hp.RequestNavigate += new RequestNavigateEventHandler(hp_RequestNavigate); 
       hyperlinks.Add(hp); 
      } 
      String[] sections = FormattedText.Split(replacements.ToArray(), StringSplitOptions.None); 
      hyperlinks.DefaultIfEmpty(null); 
      for (int i = 0, l = sections.Length; i < l; i++) { 
       this.Inlines.Add(sections.ElementAt(i)); 
       if (hyperlinks.ElementAtOrDefault(i) != null) { 
        this.Inlines.Add(hyperlinks[i]); 
       } 
      } 
     } 

     void hp_RequestNavigate(object sender, RequestNavigateEventArgs e) { 
      RequestNavigate(sender, e); 
     } 

     // 
     // Summary: 
     //  Occurs when navigation events are requested. 
     public event RequestNavigateEventHandler RequestNavigate; 
    } 

Le uniche due cose io non sono troppo felice con la mia implementazione è che:

a) ho dovuto hack-nascondere la proprietà Text esistente, perché non sapevo come prevenire che la proprietà di ignorare le cose che faccio

B) (Relativo a A) devo chiamare AssignInlines ogni volta il campo FormattedText è impostato (che dovrebbe essere solo una volta admittidly), ma questo è ancora una volta, fino a non saper agganciare nel metodo che fa in realtà la mostrare cose (aspettandosi di trovare PreRender, Render event o simili, comunque non potrei), quindi se qualcuno sa come farlo, sarebbe fantastico :).

-2

Ecco la mia soluzione:

<TextBlock x:Name="MyTextBlock" Grid.Column="1" Text="{x:Static resource:ResourceFile.Message}" Style="{StaticResource MyTextStyle}" > 
    <Hyperlink> 
      click here 
    </Hyperlink> 
</TextBlock> 
Problemi correlati