ContentPresenter в ControlTemplate не может изменить вложенное свойство зависимости
Почему следующий упрощенный код не устанавливает размер шрифта TextBlock равным 50?
<Window.Resources>
<ControlTemplate TargetType="ContentControl" x:Key="Test">
<ContentPresenter TextBlock.FontSize="50" />
</ControlTemplate>
</Window.Resources>
<Grid>
<ContentControl Template="{StaticResource Test}">
<TextBlock>Test should be rendered big</TextBlock>
</ContentControl>
</Grid>
Если я изменю значение свойства FontSize, Visual Studio покажет мне текст в нужном мне размере. После компиляции или запуска приложения размер текстового блока всегда сбрасывается до размера по умолчанию.
Я также тестировал различные версии со стилями и встроенными ресурсами, но я всегда заканчиваю ситуацией, в которой я не могу установить наследование вложенных dp из ControlTemplate, который содержит ContentPresenter. Это по замыслу?
3 ответа
Я нашел причину такого поведения - это по замыслу:
Если ContentControl уже является WPF-элементом, он создается перед его использованием в ContenPresenter. Поэтому логическим родителем элемента является ContentControl. Я могу проверить это, изменив разметку ContentControl следующим образом:
<ContentControl Template="{StaticResource Test}" TextBlock.FontSize="50">
<TextBlock>
This text now is shown with a size of 50
</TextBlock>
</ContentControl>
В этом примере размер текста составляет 50 по желанию. Я могу доказать эту аргументацию также с помощью wpf-визуализатора Visual Studio. Родителем является ContentControl, и через dp-наследование FontSize берется из родительского (ContentControl), а текст отображается с размером 50!
Другое поведение может наблюдаться, если ContentControl содержит только текст в качестве содержимого:
<Window.Resources>
<ControlTemplate x:Key="Test" TargetType="{x:Type ContentControl}">
<ContentPresenter TextBlock.FontSize="50"/>
</ControlTemplate>
</Window.Resources>
<Grid>
<ContentControl Template="{StaticResource Test}">
This text is shown with a size of 50
</ContentControl>
</Grid>
В этом случае TextBox создается с помощью ContentPresenter, потому что текст не может быть введен в визуальном дереве. У текстового поля нет родителя, но свойство TemplateParent приводит к ContentPresenter в качестве родителя TextBoxes, а DP-система получает значение FontSize через наследование присоединенного свойства зависимостей от ContentPresenter. Вот почему в этом сценарии размер шрифта изменяется на 50.
Различные сценарии описаны здесь.
Я не понимаю, почему VS2010 показывает FontSize 50 перед компиляцией.
Как насчет:
<Window.Resources>
<ControlTemplate TargetType="ContentControl"
x:Key="Test">
<Border TextBlock.FontSize="50">
<ContentPresenter />
</Border>
</ControlTemplate>
</Window.Resources>
<Grid>
<ContentControl Template="{StaticResource Test}">
<TextBlock>Test should be rendered big</TextBlock>
</ContentControl>
</Grid>
Это интересно, потому что я получил что-то подобное, чтобы работать. Есть ли разница?
<Style x:Key="SingleWaveItemContainerStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Background="{StaticResource WindowBackgroundColor}">
<Border Width="125" x:Name="BorderItem" Height="60" Margin="5" BorderThickness="2" ClipToBounds="True" BorderBrush="{StaticResource ViperPanelBorderColor}" Style="{StaticResource ButtonBorderStyle}">
<Rectangle x:Name="BackgroundRec" Fill="{StaticResource ViperPanelBorderColor}" Stroke="Transparent" Width="125" Height="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ContentPresenter Name="TheContentPresenter" Width="115" Height="60" Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="BorderItem" Property="BorderBrush" Value="{StaticResource NavBar_HighlightBrush}"/>
<Setter TargetName="BackgroundRec" Property="Fill" Value="{StaticResource NavBar_HighlightBrush}"/>
<Setter TargetName="TheContentPresenter" Property="TextElement.Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="SingleWaveDataTemplate" DataType="ListBoxItem">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Text="{Binding Name, Mode=OneWay}" Width="{Binding ElementName=this, Path=Content.DesiredWidth}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="8" Text="{Binding CreationDate, Mode=OneWay}" Width="{Binding ElementName=this, Path=Content.DesiredWidth}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
На странице xaml у меня есть:
<ListBox Background="Transparent" ItemTemplate="{StaticResource SingleWaveDataTemplate}" ItemContainerStyle="{StaticResource SingleWaveItemContainerStyle}" BorderThickness="0" ItemsSource="{Binding AllModes, Mode=OneWay}" Height="{Binding ElementName=this, Path=Parent.Height}" SelectedItem="{Binding CurrentSingleWaveModeViewModel, Mode=TwoWay}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Height="{Binding ElementName=Parent, Path=Height}" Background="{StaticResource WindowBackgroundColor}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Возможно, мы ДОЛЖНЫ использовать шаблоны данных, чтобы получить желаемый эффект?