我有一个TextBlock,我想显示一个用户名,并像这样发送电子邮件:
Firstname Lastname (Email)
但是,如果用户没有存档电子邮件,我不想放入(电子邮件)部分。我还想把电子邮件用斜体。通常情况下,我会使用TextBlock并为文本的各个部分添加运行,但我找不到从XAML动态更改TextBlock内联的方法。
我试过这个:
<TextBlock.Triggers>
<DataTrigger Binding="{Binding Path=HasEmail}" Value="True">
<Setter Property="Inlines" TargetName="contactTagNameEmailTextBlock">
<Setter.Value>
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" />
<Run Text="(" />
<Run Text="{Binding Path=Email}" />
<Run Text=")" />
</Setter.Value>
</Setter>
</DataTrigger>
</TextBlock.Triggers>
但VS抱怨该值设置不止一次(由于多次运行)。我怎么能绕过这个?或者,如果我可以在整个FrameworkElement上设置绑定,那将非常方便。例如,如果我可以在我的网格中放置一个占位符,我想放置一个自定义控件,我在这个绑定对象后面的代码中构造,那将是最好的。
感谢。
答案 0 :(得分:5)
这样的事情应该有效:
<Window.Resources>
<BooleanToVisibility x:Key="visibilityConverter"/>
</Window.Resources>
...
<TextBlock>
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" />
<TextBlock Visibility="{Binding HasEmail, Converter={StaticResource visibilityConverter}}">
<Run Text="(" />
<Run Text="{Binding Path=Email}" />
<Run Text=")" />
</TextBlock>
</TextBlock>
答案 1 :(得分:2)
查看Multibinding和StringFormat
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1}">
<Binding Path="LastName" />
<Binding Path="FirstName" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
如果没有电子邮件,您应该可以隐藏()。
答案 2 :(得分:0)
这里说的嵌套TextBlock元素的答案将导致布局问题。例如,外部TextBlock将不再适当地遵守TextTrimming设置。
这是一种更好的方法,通过触发器*为您提供运行设置的灵活性,这仍然允许正确的布局。
注意:我添加了格式化属性(Foreground,Bold)以显示您在此处使用Runs而不是简单的多重绑定的原因。使用运行(或任何内联)允许您格式化TextBlock的文本,但仍然让它尊重布局(即TextTrimming按预期工作等)。
<ContentControl x:Name="TextBlockPresenter">
<TextBlock TextTrimming="CharacterEllipsis" IsHitTestVisible="False">
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" FontWeight="Bold" />
<Run Text="(" Foreground="Gray" />
<Run Text="{Binding Path=Email}" Foreground="Gray" />
<Run Text=")" Foreground="Gray" />
</TextBlock>
</ContentControl>
[SomeTriggerArea]
<DataTrigger Binding="{Binding Path=HasEmail}" Value="False">
<Setter TargetName="TextBlockPresenter" Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<TextBlock TextTrimming="CharacterEllipsis" IsHitTestVisible="False">
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" FontWeight="Bold" />
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
[/SomeTriggerArea]
*从技术上讲,您不是通过触发器设置运行。您正在设置一个全新的模板,该模板具有定义了正确运行的TextBox。
如果你在控件中使用这样的运行来设置IsHitTestVisible为False也是一个好主意,你可能想要响应鼠标命中,然后走可视树(即你在哪里听一只右鼠标的TreeView) -down,遍历树以找到TreeViewItem并将IsSelected设置为true。)这是因为运行将响应鼠标,但它们不是FrameworkElement,因此当您使用e.OriginalSource调用VisualTreeHelper.GetParent时,您将得到一个例外。简单地禁止TextBlock参与鼠标事件可以避免这种情况。