如何从C#代码生成此xaml:
目前:
<TextBlock>
Click <Hyperlink Command="{Binding MyCommand}">here</Hyperlink> to continue.
</TextBlock>
我想要的是什么:
<TextBlock Text="{Binding MyTextWithHyperlink, Mode=OneWay}" />
public string MyTextWithHyperlink
{
get
{
return ""; //???
}
}
<小时/> 是的,我有正当理由这样做,而不是在xaml。 :)
UPDATE:这就是我想返回String的原因,因为IDataError返回一个字符串......
String IDataError.this[String columnName]
{
get
{
if (columnName == "MyProperty")
{
if (something1) return ""; //????
if (something2) return "some other string";
}
return null;
}
}
答案 0 :(得分:3)
不幸的是,没有简单的方法可以做到这一点......据我所知,你能做的最好的事情就是返回一个XAML字符串并使用转换器来解析它。
警告:未来的丑陋代码......
<强> XAML 强>
<Window.Resources>
<local:XamlToTextBlockConverter x:Key="xamlConverter" />
</Window.Resources>
<Grid>
<ContentControl Content="{Binding MyTextWithHyperlink, Converter={StaticResource xamlConverter}}" />
</Grid>
<强>转换器强>
public class XamlToTextBlockConverter : IValueConverter
{
#region Implementation of IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string xaml = value as string;
if (xaml == null)
return Binding.DoNothing;
const string textBlockFormat =
@"<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</TextBlock>";
string fullXaml = string.Format(textBlockFormat, xaml);
return (TextBlock)XamlReader.Parse(fullXaml);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
<强>视图模型强>
public string MyTextWithHyperlink
{
get { return "Click <Hyperlink Command=\"{Binding MyCommand}\">here</Hyperlink> to continue"; }
}
请注意使用ContentControl
而不是TextBlock
:这是因为TextBlock.Text
属性只能包含纯文本,而不是格式化文档和Inlines
属性不能绑定,因为它不是依赖属性(无论如何它只是readonly)。相反,我们在转换器中手动创建TextBlock
并将其分配给ContentControl
的内容。
这绝对不是一个非常优雅的解决方案,但它有效......
答案 1 :(得分:2)
此控件可替代TextBlock。它具有可绑定的MarkupText属性,该属性可以理解在指定TextBlock内容时使用的相同语法。
用法:
<local:MarkupTextBlock MarkupText="{Binding MyText}"/>
在C#中
public string MyText
{
get
{
return "My <Bold>link</Bold> is <Hyperlink NavigateUri='http://search.msn.com'>MSN</Hyperlink>.";
}
}
控制源代码:
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
/// <summary>
/// The markup text block is a replacement for <see cref="TextBlock"/>
/// that allows to specify markup content dynamically.
/// </summary>
[ContentProperty("MarkupText")]
[Localizability(LocalizationCategory.Text)]
public class MarkupTextBlock : TextBlock
{
/// <summary>
/// The markup text property.
/// </summary>
public static readonly DependencyProperty MarkupTextProperty = DependencyProperty.Register(
"MarkupText",
typeof( string ),
typeof( MarkupTextBlock ),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnTextMarkupChanged));
private const string FlowDocumentPrefix =
"<FlowDocument xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'><Paragraph><Span>";
private const string FlowDocumentSuffix = "</Span></Paragraph></FlowDocument>";
/// <summary>
/// Initializes a new instance of the <see cref="MarkupTextBlock"/> class.
/// </summary>
/// <param name="markupText">
/// The markup text.
/// </param>
public MarkupTextBlock(string markupText)
{
MarkupText = markupText;
}
/// <summary>
/// Initializes a new instance of the <see cref="MarkupTextBlock"/> class.
/// </summary>
public MarkupTextBlock()
{
}
/// <summary>
/// Gets or sets content of the <see cref="MarkupTextBlock"/>.
/// </summary>
[Localizability(LocalizationCategory.Text)]
public string MarkupText
{
get { return Inlines.ToString(); }
set { SetValue(MarkupTextProperty, value); }
}
private static void OnTextMarkupChanged(
DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var markupTextBlock = dependencyObject as MarkupTextBlock;
if( markupTextBlock != null )
{
var flowDocument = new StringBuilder();
flowDocument.Append(FlowDocumentPrefix);
flowDocument.Append(dependencyPropertyChangedEventArgs.NewValue);
flowDocument.Append(FlowDocumentSuffix);
var document = (FlowDocument) XamlReader.Parse(flowDocument.ToString());
var paragraph = document.Blocks.FirstBlock as Paragraph;
if( paragraph != null )
{
var inline = paragraph.Inlines.FirstInline;
if( inline != null )
{
paragraph.Inlines.Remove(inline);
markupTextBlock.Inlines.Clear();
markupTextBlock.Inlines.Add(inline);
}
}
}
}
}
答案 2 :(得分:1)
所以你试图从你的视图模型中指定可视树?不好的主意。
相反,为什么不简单地根据验证设置状态属性并基于此触发可视树?您可以使用触发器或使用可视状态管理器来执行此操作。