【问题标题】:Style content via setters v ContentTemplate通过 setter v ContentTemplate 设置内容样式
【发布时间】:2020-10-13 06:08:57
【问题描述】:

第一种样式的 xaml 可以按我的意愿工作,生成一个带有 Wingding 字形的按钮,使用 setter 来布置内容及其属性。这种风格的第二个版本尝试做同样的事情,但使用 DataTemplate 作为 Content,但它只显示 DataTemplate 的类型(即 System.Windows.DataTemplate)。

  1. 为什么第 2 版显示的内容与第 1 版不同?
  2. 假设修复是微不足道的,出于个人喜好之外的任何原因,一个版本的样式是否比另一个版本更可取?

注意:我正在显示绑定和触发器,以防其中有影响内容的东西,但这只是样式的第一部分会有所不同

干杯,
贝瑞尔

样式 1

显示:

<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
    <Setter Property="Content" Value="a" />
    <Setter Property="Foreground" Value="Navy" />
    <Setter Property="FontFamily" Value="Wingdings 3" />
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="FontSize" Value="18" />
    <Setter Property="Width" Value="30" />
    <Setter Property="Height" Value="Auto" />

    <!--What makes it an Edit button-->
    <Setter Property="Command" Value="{Binding ActivateThisSatelliteVmCommand}"/>
    <Setter Property="ToolTip">
        <Setter.Value>
            <TextBlock>
                <TextBlock.Text>
                    <Binding Path="HeaderLabel" StringFormat="{resx:Resx ResxName=Smack.Core.Presentation.Resources.MasterDetail, Key=Item_Edit_Label}"/>
                </TextBlock.Text>
            </TextBlock>
        </Setter.Value>
    </Setter>

    <!-- WHen its available -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="theBorder" CornerRadius="4">
                    <ContentPresenter x:Name="theContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter TargetName="theContent" Property="Visibility" Value="Hidden"/>
                        <Setter TargetName="theBorder" Property="Background" Value="Transparent"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
                        <Setter TargetName="theBorder" Property="Background" Value="Orange"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

样式 2

显示“System.Windows.DataTemplate”

<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
    <Setter Property="Content">
        <Setter.Value>
            <DataTemplate>
                <TextBlock Text="a" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
            </DataTemplate>
        </Setter.Value>
    </Setter>

    <!--What makes it an Edit button-->
    <Setter Property="Command" Value="{Binding ActivateThisSatelliteVmCommand}"/>
    <Setter Property="ToolTip">
        <Setter.Value>
            <TextBlock>
                <TextBlock.Text>
                    <Binding Path="HeaderLabel" StringFormat="{resx:Resx ResxName=Core.Presentation.Resources.MasterDetail, Key=Item_Edit_Label}"/>
                </TextBlock.Text>
            </TextBlock>
        </Setter.Value>
    </Setter>

    <!-- When its available -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="theBorder" CornerRadius="4">
                    <ContentPresenter x:Name="theContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter TargetName="theContent" Property="Visibility" Value="Hidden"/>
                        <Setter TargetName="theBorder" Property="Background" Value="Transparent"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
                        <Setter TargetName="theBorder" Property="Background" Value="Orange"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

【问题讨论】:

  • 从 TextBlock 中移除包装 DataTemplate 是否解决了问题?
  • @LPL。不,没有 DataTemplate 包装它的运行时错误:错误 1 ​​'System.Windows.Controls.TextBlock' 不是 Setter 上的 'System.Windows.Controls.ContentControl.ContentTemplate' 属性的有效值。
  • 删除 DataTemplate 对我有用。您应该将您的内容放入 content 属性中。无需模板。
  • @Phil。当您尝试与多个父母一起使用该样式时,这将导致不同的问题。见Rachel's blog post for the gory details

标签: wpf xaml data-binding mvvm styles


【解决方案1】:

您的Content 属性设置为DataTemplate

DataTemplates 旨在与Template 属性一起使用,而不是通过Content 属性直接插入到VisualTree 中

更改您的样式设置器以设置ContentTemplate 而不是Content,它应该可以正常工作

<Setter Property="ContentTemplate">
    <Setter.Value>
        <DataTemplate>
            <TextBlock Text="a" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
        </DataTemplate>
    </Setter.Value>
</Setter>

至于你的第二个问题,我更喜欢第一个,因为它更简单,而且我认为它可能包含更少的可视树中的元素(我必须仔细检查)

【讨论】:

  • 宾果游戏,不足为奇。它证实了我的怀疑,即当只有极少数人始终能够回答本应是平凡的问题时,WPF 的学习曲线出奇地陡峭。干杯
  • 我还添加了在我的父模板中使用 &lt;ContentPresenter /&gt; 而不是 &lt;ContentControl Content="{TemplateBinding Content}" /&gt; 以使其工作,但现在我不能再覆盖视图中的内容了。使其不是可覆盖的默认值。 (这是我最初的目标)
【解决方案2】:

我找到了解决此问题的另一种方法:

<Style x:Key="DefaultButtonBaseStyle" TargetType="{x:Type ButtonBase}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ButtonBase}">
                <Grid>
                    <Border x:Name="BackBorder" Margin="0" Padding="0"
                            BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding BorderBrush}"/>
                    <Border x:Name="FrontBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"
                            Margin="0" Padding="{TemplateBinding Padding}"
                            CornerRadius="{Binding ElementName=BackBorder, Path=CornerRadius}">
                        <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

【讨论】:

    猜你喜欢
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 2013-02-18
    • 1970-01-01
    • 2011-03-15
    • 2012-11-17
    • 2020-11-15
    相关资源
    最近更新 更多