【问题标题】:How to Target WPF child controls with nested styles by name?如何按名称定位具有嵌套样式的 WPF 子控件?
【发布时间】:2021-05-27 12:44:52
【问题描述】:

我正在尝试在 WPF 中创建自定义按钮。

我有 Button 的基本 XAML,按钮内有两个 TextBlock 控件。一个是由 FontAwesome 渲染的图像,一个是文本。

<TextBlock Style="{DynamicResource mediumLabel}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="4">SETTINGS</TextBlock>
<Button  Grid.Column="1" Grid.Row="5" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" Style="{DynamicResource mainButton}" Template="{DynamicResource mainButtonTemplate}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="40"/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>

        <TextBlock x:Name="Image" Grid.Row="1" Grid.Column="0">cogs</TextBlock>
        <TextBlock x:Name="Label" Grid.Row="1" Grid.Column="1" Text="SETTINGS" />
    </Grid>
</Button>

我在App.xaml 中定义了全局样式。

我可以单独定位这三个元素中的每一个,在我的App.xaml 中使用单独的样式。

我想做什么,我想只是为了组织和便于将来使用,我想为Button 设置一个样式,并使用嵌套样式来定位两个TextBlock 控件中的每一个。每个都会有不同的样式,所以我不能定位 TextBlock 类型。我想按名称引用它们。

我尝试引用主要的control_name.childcontrol_name,以及控件名称。

我似乎无法在搜索时获得足够的信息来说明如何执行此操作,因为我可能正在搜索错误的术语...

我对嵌套样式的尝试,针对嵌套样式定位进行了两次尝试。

<Style x:Key="mainButton" TargetType="Button">
    <Setter Property="Background" Value="White"/>
    <Setter Property="Foreground" Value="DarkSlateGray"/>
    <Setter Property="FontSize"  Value="14"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="DodgerBlue"/>
        </Trigger>
    </Style.Triggers>

    <Style.Resources>
        <Style TargetType="{x:Reference Image}">
            <Setter Property="FontFamily" Value="/Genesis_desktop;component/tools/fontawesome-free-5.15.1-desktop/otfs/#Font Awesome 5 Free Solid"/>
            <Setter Property="FontSize"  Value="14"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="ForeGround" Value="orange"/>
        </Style>

        <Style TargetType="{x:Reference mainButton.Label}">
            <Setter Property="FontSize"  Value="14"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
    </Style.Resources>
</Style>

【问题讨论】:

    标签: wpf xaml styles app.xaml


    【解决方案1】:

    你想错了。搜索其目标的不是Style。这是搜索其Style 的目标。
    XAML 解析器创建标记对象的实例,例如一个&lt;TextBlock&gt;,然后在检查本地FrameworkElement.Style 属性后,遍历逻辑树以查找是否有一个Style 定义了该实例化类型或具有与请求的资源键匹配的键。

    你想要的也是非常低效的,因为名称范围内的名称必须是唯一的,并且名称范围总是非常“小”。这种元素名称驱动的映射将需要一个仅匹配单个控件的显式样式。并且需要提前知道这个控件的名称。
    这意味着您,这个单独样式的作者,可以直接访问命名控件。
    因此,您可以直接在本地 ResourceDictionary 中定义样式,例如TextBlock.Resources.
    这具有相同的效果:Style 现在适用于单个 TextBlock 元素,您知道它的名称。

    如果您需要在不同的父 ResourceDictionary 上声明独占样式或作为合并资源,您通常通过应用 x:Key 指令命名 Style,然后显式请求此资源,例如通过使用StaticResource 标记扩展。

    同样x:Reference 返回一个名称而不是TypeTargetType 属性的类型为 Type。此属性使用TypeConverter,它允许分配一个字符串值,然后将其转换为Type

    你想要的默认是不可能的。样式是纯类型特定的(当定义为隐式资源时)或由其x:Key 值显式映射(作为附加约束)。另一方面,您想要的已经以不同的形式存在,可以通过使用本地资源或x:Keydirective 以及StaticResourceDynamicResource 标记扩展来实现。

    【讨论】:

      【解决方案2】:

      您的样式的问题是 nested 样式在其Resources 中定义。这些只能在此样式的范围内访问。因此,按钮不能,因为它具有不同的范围。

      我不认为以这种方式嵌套样式是可能的,但您也可以为按钮的Content 创建一个DataTemplate 并将样式嵌套在那里。为它们分配一个密钥并从您的TextBlocks 引用它们。在您的mainButton 样式中,您可以添加一个setter 来将ContentTemplate 设置为此模板。您还可以在按钮上显式设置ContentTemplate(但这意味着您必须将数据模板移出样式)。我希望这是您想要实现的那种嵌套或封装。

      <Style x:Key="mainButton" TargetType="Button">
         <Style.Resources>
            <DataTemplate x:Key="MyButtoDataTemplate">
               <DataTemplate.Resources>
                  <Style x:Key="ImageStyle" TargetType="{x:Type TextBlock}">
                     <Setter Property="FontFamily" Value="/Genesis_desktop;component/tools/fontawesome-free-5.15.1-desktop/otfs/#Font Awesome 5 Free Solid"/>
                     <Setter Property="FontSize"  Value="14"/>
                     <Setter Property="VerticalAlignment" Value="Center"/>
                     <Setter Property="HorizontalAlignment" Value="Center"/>
                     <Setter Property="Foreground" Value="orange"/>
                  </Style>
                  <Style x:Key="LabelStyle" TargetType="{x:Type TextBlock}">
                     <Setter Property="FontSize"  Value="14"/>
                     <Setter Property="VerticalAlignment" Value="Center"/>
                     <Setter Property="HorizontalAlignment" Value="Left"/>
                  </Style>
               </DataTemplate.Resources>
               <Grid>
                  <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="40"/>
                     <ColumnDefinition Width="200"/>
                  </Grid.ColumnDefinitions>
      
                  <TextBlock x:Name="Image" Grid.Column="0" Style="{StaticResource ImageStyle}">cogs</TextBlock>
                  <TextBlock x:Name="Label" Grid.Column="1" Style="{StaticResource LabelStyle}" Text="SETTINGS" />
               </Grid>
            </DataTemplate>
         </Style.Resources>
         <Setter Property="Background" Value="White"/>
         <Setter Property="Foreground" Value="DarkSlateGray"/>
         <Setter Property="FontSize"  Value="14"/>
         <Setter Property="BorderThickness" Value="0"/>
         <Setter Property="Cursor" Value="Hand"/>
         <Setter Property="ContentTemplate" Value="{StaticResource MyButtoDataTemplate}"/>
         <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
               <Setter Property="Foreground" Value="DodgerBlue"/>
            </Trigger>
         </Style.Triggers>
      </Style>
      

      您的Button 定义被简化为这样,因为样式已经定义了一切:

      <Button  Grid.Column="1"
               Grid.Row="5"
               Grid.ColumnSpan="2"
               HorizontalAlignment="Stretch"
               Style="{DynamicResource mainButton}"
               Template="{DynamicResource mainButtonTemplate}"/>
      

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 2015-09-11
        • 1970-01-01
        • 2015-05-27
        • 2019-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多