在XAML中有条件地呈现数据模板

sno*_*att 5 xaml uwp uwp-xaml

我有一个文本块列表,可能包括内部网址,如下:

  • 构建失败,请在此处查看更多内容:http:// ...
  • 构建成功
  • App http:// myapp /无法启动,请点击此处:http:// ...

我需要在UWP应用程序中显示此(无限)列表.考虑到此列表可以在应用程序内的多个视图中使用,我将其作为一个通用模板:

<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>
Run Code Online (Sandbox Code Playgroud)

在此模板中,链接被视为常规文本(预期).据我所知,要使链接工作,我需要将它们包装成<HyperLink>标记,但我不能在模板中执行此操作,因为我不知道链接的确切位置以及将显示多少链接.

有没有办法实现一些渲染器方法,可以<TextBlock>在代码中生成项的body(),处理传递的值?

可能转换器可以帮助我,但如果我理解正确,它只接受绑定的值,我需要引用整个实例.

UPD:从接受的答案中扩展解决方案:

资源字典:

<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>
Run Code Online (Sandbox Code Playgroud)

处理器中某处的处理器:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定这是最好的方法,但它确实有效.我只需要预处理绑定值并将所有URL包装成超链接标记:

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

我认为这应该适用于任何其他内容,例如 <InlineUIContainer>

15e*_*153 1

您可以编写一个附加行为,使用 来将字符串解析为 XAML XamlReader.Load(Stream),并将生成的控件添加到目标控件。这是我写的一个TextBlock内容,它可以包括Hyperlink. 这是针对 WPF 而非 UWP;可能存在一些差异。

您必须做一些额外的工作:它需要一个非 XAML 字符串,并且在解析为 XAML 之前,它必须找到 URL 并将其替换为Hyperlink字符串中的 XAML 元素。然后你会解析它。

将第二部分放入值转换器中会更干净。叫它HyperLinksToXAMLConverter

<TextBlock
    local:XAMLText="{Binding status, Converter={StaticResource HyperLinksToXAML}}"
    />
Run Code Online (Sandbox Code Playgroud)