【发布时间】: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。
编辑:这个模板的完整用法是在一个样本按钮列表中,并且列表的源绑定到一个名为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>
【问题讨论】:
-
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