在 ControlTemplate DataTrigger 中更改按钮背景
Changing button background in ControlTemplate DataTrigger
我想为 "color swatch" 按钮定义 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")。
我似乎无法弄清楚如何在检查背景颜色的模板中设置触发器,如果它是透明的,请为背景使用不同的画笔 属性。我尝试将 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。
编辑:此模板的完整用法在样本按钮列表中,列表的源绑定到一个名为 ColorList
的 ObservableCollection<Brush>
,其中填充了 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>
您可以通过绑定到 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
属性
感谢@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)。
我想为 "color swatch" 按钮定义 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")。
我似乎无法弄清楚如何在检查背景颜色的模板中设置触发器,如果它是透明的,请为背景使用不同的画笔 属性。我尝试将 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。
编辑:此模板的完整用法在样本按钮列表中,列表的源绑定到一个名为 ColorList
的 ObservableCollection<Brush>
,其中填充了 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>
您可以通过绑定到 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
属性
感谢@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)。