/ / Usar explicitamente TextBlock no conteúdo do Label faz com que o ContentPresenter se comporte de maneira estranha - .net, wpf, templates, xaml, label

O uso explícito do TextBlock no conteúdo do Label faz o ContentPresenter se comportar de forma estranha - .net, wpf, templates, xaml, label

Eu tenho um costume ControlTemplate com duplo ContentPresenters. O modelo é aplicado a um Label. Quando eu definir "Polvo aleatório"(apenas texto) como Conteúdo do rótulo, funciona exatamente como o esperado. Quando eu definir "<TextBlock> Polvo aleatório </TextBlock>"como o Conteúdo, não funciona (apenas um ContentPresenter é representado visualmente). Eu uso o seguinte código para reproduzir o comportamento:

<Window x:Class="WeirdTextBlock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Window.Resources>
<Style TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Border BorderBrush="Red" BorderThickness="1" Padding="2">
<Grid>
<ContentPresenter />
<ContentPresenter Margin="2,2,0,0" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

<Grid Margin="20" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Label Grid.Row="0">
Random octopus
</Label>

<Label Grid.Row="2">
<TextBlock>Random octopus</TextBlock>
</Label>
</Grid>
</Window>

E aqui você pode ver como fica:

http://i56.tinypic.com/1zgdull.png

eu pensei quando você insere apenas texto na propriedade Content, ele é encapsulado por TextBlock, então por que exatamente o visual do segundo Labelrepresentação diferente da primeira? E como fazer o segundo Label se comportar corretamente (torná-lo parecido com o primeiro Label, mas apenas modificando o modelo)? Obrigado!

Respostas:

1 para resposta № 1

A diferença é ...

  • Quando você define uma string como Conteúdo para um Label, uma TextBlock é gerado para a string em cada ContentPresenter.
  • Quando você define um TextBlock diretamente como Content para Label, vai acabar onde você tem o ContentPresenter, mas como você só tem um TextBlock, só pode estar em um lugar de cada vez.

Atualizar

<Style TargetType="Label">
<Style.Resources>
<local:TypeOfConverter x:Key="TypeOfConverter"/>
<Style TargetType="TextBlock">
<Setter Property="Background" Value="Transparent"/>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Border BorderBrush="Red" BorderThickness="1" Padding="2">
<Grid>
<ContentPresenter Name="content" Grid.ZIndex="2"/>
<ContentPresenter Name="secondContent" Grid.ZIndex="1" Margin="2,2,0,0" Visibility="Collapsed"/>
<Border Grid.ZIndex="1">
<Border.RenderTransform>
<TranslateTransform X="2" Y="2"/>
</Border.RenderTransform>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=content, Path=Content}"/>
</Border.Background>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},
Path=Content,
Converter={StaticResource TypeOfConverter}}"
Value="{x:Type sys:String}">
<Setter TargetName="secondContent" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

TypeOfConverter

public class TypeOfConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (value == null) ? null : value.GetType();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

3 para resposta № 2

O problema subjacente aqui é que você está tentando colocar um visual (o TextBlock) em dois lugares diferentes ao mesmo tempo. Um visual só pode ter um único pai, portanto, um dos apresentadores de conteúdo "ganha" e o outro não tem nenhum conteúdo.

Se tudo o que você deseja fazer é ter uma cópia visual do TextBlock então use um VisualBrush.