2017-01-04 3 views
4

ich eine Liste von Textblöcke haben, die Urls innen umfassen, smth wie:Bedingte Wiedergabe der Datenvorlage in XAML

  • Erstellen fehlgeschlagen ist, sehen Sie hier mehr: http: // ...
  • Bauen gelang
  • App http://myapp/ nicht gestartet werden können, finden Sie hier mehr: http: // ...

ich brauche in einer UWP App diese (endlos) Liste anzuzeigen. In Anbetracht dieser Liste kann in mehreren Ansichten in der App verwendet werden, habe ich es eine gemeinsame Vorlage:

<ResourceDictionary> 
    <ControlTemplate x:Key="ListItemTemplate" TargetType="ItemsControl"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="50"/> 
     <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Image Grid.Column="0" Source="{Binding image_url}"/> 
     <TextBlock Grid.Column="1" Text="{Binding status}"/> 
    </Grid> 
    </ControlTemplate> 
</ResourceDictionary> 

in dieser Vorlage Links wie normaler Text behandelt werden (voraussichtlich). Wie ich verstehe, um Links arbeiten zu können, muss ich sie in <HyperLink> Tag wickeln, aber ich kann dies nicht in der Vorlage tun, weil ich nicht weiß, wo genau Verbindungen sein werden und wie viele von ihnen angezeigt werden.

Gibt es eine Möglichkeit, eine Renderer-Methode zu implementieren, die den Textkörper des Elements (<TextBlock>) im Code generieren könnte, übergebenen Wert verarbeiten?

Wahrscheinlich Konverter könnte mir helfen, aber wenn ich richtig verstehe, es akzeptieren nur Wert von Bindung, und ich muss die gesamte Instanz verweisen.

UPD: Ausbau Lösung aus der Antwort akzeptiert:

Ressourcen Wörterbuch:

<ResourceDictionary xmlns:resources="using:NamespaceWithTextBlockExt"> 
    <ControlTemplate x:Key="ListItemTemplate" TargetType="ItemsControl"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="50"/> 
     <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Image Grid.Column="0" Source="{Binding image_url}"/> 
     <TextBlock Grid.Column="1" resources:TextBlockExt.XAMLText="{Binding Text}"/> 
    </Grid> 
    </ControlTemplate> 
</ResourceDictionary> 

Prozessor irgendwo in Ihrem Projekt:

public static class TextBlockExt 
{ 
    public static String GetXAMLText(TextBlock obj) 
    { 
     return (String)obj.GetValue(XAMLTextProperty); 
    } 

    public static void SetXAMLText(TextBlock obj, String value) 
    { 
     obj.SetValue(XAMLTextProperty, value); 
    } 

    /// <summary> 
    /// Convert raw string from ViewModel into formatted text in a TextBlock: 
    /// 
    /// @"This <Bold>is a test <Italic>of the</Italic></Bold> text." 
    /// 
    /// Text will be parsed as XAML TextBlock content. 
    /// 
    /// See WPF TextBlock documentation for full formatting. It supports spans and all kinds of things. 
    /// 
    /// </summary> 
    public static readonly DependencyProperty XAMLTextProperty = 
     DependencyProperty.RegisterAttached("XAMLText", typeof(String), typeof(TextBlockExt), 
              new PropertyMetadata("", XAMLText_PropertyChanged)); 

    private static void XAMLText_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is TextBlock) 
     { 
      var ctl = d as TextBlock; 

      try 
      { 
       // XAML needs a containing tag with a default namespace. We're parsing 
       // TextBlock content, so make the parent a TextBlock to keep the schema happy. 
       // TODO: If you want any content not in the default schema, you're out of luck. 
       var value = e.NewValue; 

       var strText = String.Format(@"<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</TextBlock>", e.NewValue); 

       TextBlock parsedContent = Windows.UI.Xaml.Markup.XamlReader.Load(strText) as TextBlock; 

       // The Inlines collection contains the structured XAML content of a TextBlock 
       ctl.Inlines.Clear(); 

       var inlines = parsedContent.Inlines.ToList(); 
       parsedContent.Inlines.Clear(); 

       // UI elements are removed from the source collection when the new parent 
       // acquires them, so pass in a copy of the collection to iterate over. 
       ctl.Inlines.Concat(inlines); 
       inlines.ForEach(x => ctl.Inlines.Add(x)); 
      } 
      catch (Exception ex) 
      { 
       System.Diagnostics.Debug.WriteLine(String.Format("Error in Ability.CAPS.WPF.UIExtensions.TextBlock.XAMLText_PropertyChanged: {0}", ex.Message)); 
       throw; 
      } 
     } 
    } 
} 

Ich bin nicht Sicher, das ist der beste Weg, bu t es funktioniert. Ich brauche nur zu Vorprozess gebunden Wert und wickeln alle URLs in Hyperlinks tags:

"App <Hyperlink NavigateUri=\"http://app/\">myapp</Hyperlink>"

Ich nehme an, dies mit anderen Inhalten arbeiten sollte, wie <InlineUIContainer>

+0

Es sollte mit allen Inhalten arbeiten, die ein Kind von 'TextBlock' sein kann. –

Antwort

1

Sie können ein angeschlossenes Verhalten schreiben, die einen String parst als XAML unter Verwendung von XamlReader.Load(Stream) und fügt das resultierende Steuerelement zum Zielsteuerelement hinzu. Here's one I wrote was es mit TextBlock Inhalt tut, der Hyperlink enthalten kann. Das ist für WPF nicht UWP; Es kann einige Unterschiede geben.

Sie müssen noch ein wenig zusätzliche Arbeit erledigen: Es würde eine Nicht-XAML-Zeichenfolge und vor dem Parsing als XAML URLs suchen und sie durch XAML Hyperlink Elemente in der Zeichenfolge ersetzen. Dann würden Sie das analysieren.

Es wäre sauberer, diesen zweiten Teil in einen Wertkonverter zu legen. Nennen Sie es HyperLinksToXAMLConverter:

<TextBlock 
    local:XAMLText="{Binding status, Converter={StaticResource HyperLinksToXAML}}" 
    /> 
+0

Vielen Dank! Ich habe diese Lösung getestet und es erlaubt mir, Inhalte zu ändern und Hyperlinks anzuzeigen. Wie erwähnt - Code sollte etwas angepasst werden. – ragzovskii

+0

@ragzovskii Super. Kannst du die UWP-Version des Codes zu deinem Q hinzufügen oder in meinem A bearbeiten? Ich werde die Bearbeitung genehmigen. –

Verwandte Themen