数据模板在XAML中的条件呈现
我有一个文本块列表,其中可能包含URL,如:数据模板在XAML中的条件呈现,xaml,uwp,uwp-xaml,Xaml,Uwp,Uwp Xaml,我有一个文本块列表,其中可能包含URL,如: 生成失败,请参阅此处的详细信息:http://... 建造成功 无法启动应用程序,请参阅此处的详细信息:http://... 我需要在UWP应用程序中显示这个(无休止的)列表。考虑到此列表可以在应用程序内的多个视图中使用,我将其作为一个通用模板: <ResourceDictionary> <ControlTemplate x:Key="ListItemTemplate" TargetType="ItemsControl"&g
- 生成失败,请参阅此处的详细信息:http://...
- 建造成功
- 无法启动应用程序,请参阅此处的详细信息:http://...
<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>
在此模板中,链接被视为常规文本(这是预期的)。据我所知,要使链接起作用,我需要将它们包装到
标记中,但我不能在模板中这样做,因为我不知道链接的确切位置和出现的数量
有没有办法实现一些渲染器方法,可以在代码中生成项的主体(
),处理传递的值
可能转换器可以帮助我,但若我理解正确,它只接受来自绑定的值,我需要引用整个实例
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>
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;
}
}
}
}
项目中的某个处理器:
<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>
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;
}
}
}
}
公共静态类TextBlockExt
{
公共静态字符串GetXAMLText(TextBlock obj)
{
返回(字符串)obj.GetValue(XAMLTextProperty);
}
公共静态void SetXAMLText(TextBlock obj,字符串值)
{
对象设置值(XAMLTextProperty,value);
}
///
///将ViewModel中的原始字符串转换为文本块中的格式化文本:
///
///@“这是对文本的测试。”
///
///文本将被解析为XAML TextBlock内容。
///
///有关完整格式,请参阅WPF TextBlock文档。它支持跨距和所有类型的内容。
///
///
公共静态只读DependencyProperty XAMLTextProperty=
DependencyProperty.RegisterAttached(“XAMLText”、typeof(String)、typeof(TextBlockText),
新的PropertyMetadata(“,XAMLText_PropertyChanged));
私有静态void XAMLText_属性已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
如果(d是文本块)
{
var ctl=d作为文本块;
尝试
{
//XAML需要具有默认命名空间的包含标记。我们正在分析
//TextBlock内容,因此将父级设置为TextBlock以使模式保持愉快。
//TODO:如果您希望任何内容不在默认模式中,那么您就倒霉了。
var值=e.NewValue;
var strText=String.Format(@“{0}”,e.NewValue);
TextBlock parsedContent=Windows.UI.Xaml.Markup.XamlReader.Load(strText)作为TextBlock;
//Inlines集合包含TextBlock的结构化XAML内容
ctl.Inlines.Clear();
var inlines=parsedContent.inlines.ToList();
parsedContent.Inlines.Clear();
//当新的父项出现时,UI元素将从源集合中删除
//获取它们,因此传入集合的副本以进行迭代。
控制内联线。连接(内联线);
ForEach(x=>ctl.inlines.Add(x));
}
捕获(例外情况除外)
{
System.Diagnostics.Debug.WriteLine(String.Format(“Ability.CAPS.WPF.UIExtensions.TextBlock.XAMLText_PropertyChanged:{0}”,ex.Message中的错误”);
投掷;
}
}
}
}
我不确定这是不是最好的方法,但它是有效的。我只需要预处理绑定值并将所有URL包装成超链接标记:
“App myapp”
我假设这应该适用于任何其他内容,例如
,您可以编写附加的行为,使用将字符串解析为XAML,并将结果控件添加到目标控件。它与TextBlock
内容一起工作,内容可以包括Hyperlink
。这是WPF而不是UWP;可能有一些不同
您需要做一些额外的工作:它需要一个非XAML字符串,在解析为XAML之前,必须找到URL并用字符串中的XAMLHyperlink
元素替换它们。然后你会解析它
将第二部分放入值转换器会更干净。将其称为HyperLinksToXAMLConverter:
<TextBlock
local:XAMLText="{Binding status, Converter={StaticResource HyperLinksToXAML}}"
/>
非常感谢!我测试了这个解决方案,它允许我修改内容和显示超链接。如前所述-代码应该稍微调整。@ragzovskii真棒。你能将UWP版本的代码添加到你的Q中,或者编辑到我的A中吗?我将批准该编辑。它应该适用于任何可以是TextBlock
子项的内容。