【问题标题】:Changing button background in ControlTemplate DataTrigger在 ControlTemplate DataTrigger 中更改按钮背景
【发布时间】:2017-02-19 02:41:47
【问题描述】:

我想为“色板”按钮定义一个 WPF ControlTemplate。本质上,我希望能够像这样使用模板:

<Button Template="{StaticResource SwatchButtonTemplate}" Background="{Binding ActiveColor}">

其中ActiveColor 是数据上下文中的Color 属性。我已经能够使用此模板实现这一目标:

<ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
    <Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
        <Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
            <ContentPresenter/>
        </Border>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="OuterBorder" Property="BorderThickness" Value="1"/>
            <Setter TargetName="InnerBorder" Property="BorderThickness" Value="1"/>
            <Setter TargetName="OuterBorder" Property="BorderBrush" Value="{StaticResource MouseOverAccentBrush}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

但是现在我想做的是,如果颜色是透明的,则为按钮背景使用特殊的画笔(例如,如果颜色是透明的,则在背景中显示一个红色的“X”)。

我似乎不知道如何在模板中设置一个触发器来检查背景颜色,如果它是透明的,请为 Background 属性使用不同的画笔。我尝试将 DataTrigger 添加到模板中:

    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            ...
        </Trigger>
        <DataTrigger Binding="{TemplateBinding Background}" Value="#00000000">
            <Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}"/>
        </DataTrigger>
    </ControlTemplate.Triggers>

但是我在使用这个时遇到了 XamlParseException。

编辑:这个模板的完整用法是在一个样本按钮列表中,并且列表的源绑定到一个名为ColorListObservableCollection&lt;Brush&gt;,其中填充了SolidColorBrushes(其中一个是透明的)

<ItemsControl ItemsSource="{Binding ColorList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button x:Name="button" Background="{Binding}"
                    Template="{StaticResource SwatchButtonTemplate}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Height="20" Rows="1" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

以及完整的模板定义:

<ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
    <Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
        <Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
            <ContentPresenter/>
        </Border>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="OuterBorder" Property="BorderThickness" Value="1"/>
            <Setter TargetName="InnerBorder" Property="BorderThickness" Value="1"/>
            <Setter TargetName="OuterBorder" Property="BorderBrush" Value="{StaticResource MouseOverAccentBrush}"/>
        </Trigger>
        <DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="#00ffffff">
            <Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}"/>
        </DataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

【问题讨论】:

  • TemplateBinding 非常有限。当它经常给您一个 SadTromboneException 时,请始终尝试Binding="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}"
  • @EdPlunkett 我刚试过,但后来我收到了这个错误:BindingExpression path error: 'Background' property not found on 'object' ''ContentPresenter' (Name='')'. ... 这是因为我的模板的结构吗?
  • 这是因为 ContentPresenter 没有名为 Background 的属性,但无论如何,某处正在尝试设置该属性。我必须查看当前状态的完整模板,才能知道它是如何尝试在 ContentPresenter 上设置背景的。如果 TargetName 仍然是 InnerBorder,并且 InnerBorder 仍然是 Border 的名称,那么您可能正在其他地方这样做。
  • @EdPlunkett 我已经添加了完整的模板定义以及它的用法。
  • 问题可能出在其他地方。用户控件对此有点过分了。

标签: wpf xaml controltemplate datatrigger


【解决方案1】:

您可以通过绑定到 Button 类型的锚来修复它,如下所示:

<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        ...
    </Trigger>
    <DataTrigger Binding="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=Button}}" Value="#00000000">
        <Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}"/>
    </DataTrigger>

这将使用您的Button 中的Background 属性

【讨论】:

    【解决方案2】:

    感谢@EdPlunkett 建议避免在数据触发器中使用“{TemplateBinding ...}”。解决方案(仅限 XAML)是使用“Self”相对源:

    <ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
        <Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
            <Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
                <ContentPresenter/>
            </Border>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="InnerBorder" Property="BorderThickness" Value="1" />
            </Trigger>
            <DataTrigger Binding="{Binding Path=Background.Color, RelativeSource={RelativeSource Self}}" Value="#00ffffff">
                <Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}" />
            </DataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    

    (另请注意,Colors.Transparent 是 #00ffffff,而不是我想的 #00000000)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 2013-02-25
      相关资源
      最近更新 更多