【问题标题】:ContentPresenter within ControlTemplate cannot change attached dependency propertyControlTemplate 中的 ContentPresenter 无法更改附加的依赖项属性
【发布时间】:2010-06-17 15:44:03
【问题描述】:

为什么下面的简化代码没有将 TextBlock 的 font-size 设置为 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 会以我想要的大小显示文本。编译或执行应用程序后,文本块的大小始终重置为其默认大小。

我还测试了带有样式和嵌入式资源的各种版本,但我总是在无法设置从包含 ContentPresenter 的 ControlTemplate 中继承附加的 dp 的情况下结束。这是设计的吗?

【问题讨论】:

  • 以前从未遇到过这样的情况,但可能是设计使然。我认为 ContentPresenter 只是将自己替换为您提供给它的内容。

标签: wpf controltemplate contentpresenter


【解决方案1】:

我找到了这种行为的原因 - 这是设计使然:

如果 ContentControl 的 Content 已经是 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,根据需要。我也可以用 Visual Studio 的 wpf-visualizer 来证明这个论点。父级是ContentControl,通过dp-inheritance,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-property 导致 ContentPresenter 作为 TextBoxes 父级,DP 系统通过从 ContentPresenter 附加的依赖属性继承来获取 FontSize-value。这就是为什么在这种情况下字体大小更改为 50。

描述了不同的场景here

我不明白的是,为什么VS2010在编译之前显示FontSize 50。

【讨论】:

    【解决方案2】:

    怎么样:

    <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>
    

    【讨论】:

    • 我看到它工作后直接从我的代码编辑器中复制了它!
    • 你编译运行了吗?当我在编辑器中复制代码时,它可以工作。编译后失败。我在 .net 3.51 下测试过,现在也在 .net 4 下测试过,同样的问题。
    【解决方案3】:

    这很有趣,因为我得到了类似这样的工作。有区别吗?

    <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>
    

    也许我们必须使用数据模板来获得想要的效果?

    【讨论】:

    • Doh,这很明显为什么有效。文本块正在由数据模板放置。这意味着对 controltemplate 的任何影响都会导致它起作用。
    猜你喜欢
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    相关资源
    最近更新 更多