我已经构建了一个ControlTemplate
,用于窗口中的所有按钮,但有一个需要额外的触发器,当触发时会更改其内容值。很明显,我不想把这个触发器添加到控件模板上,因为它会影响使用这个控件模板的所有其他按钮。因此,我要做的是将数据触发器添加到按钮特定的样式中,然后引用内容名称,并在我认为很容易的样式中直接更改它。
这就是我目前所得到的:
<Button HorizontalAlignment="Right"
VerticalAlignment="Top"
Width="34"
BorderThickness="0"
Height="30"
Padding="0"
Click="OnMaximiseClick">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource WindowButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximised">
<Setter TargetName="MaxPath"
Property="Data"
Value="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Path x:Name="MaxPath"
Width="10"
Height="10"
Data="F1M0,0L0,9 9,9 9,0 0,0 0,3 8,3 8,8 1,8 1,3z"
SnapsToDevicePixels="True"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" />
</Button>
问题在于Setter
无法访问TargetName="MaxPath"
,我也尝试过{Binding ElementName=MaxPath}
,但陷入僵局。我知道我可以在按钮样式中再次构建ControlTemplate
,但它有很多触发器,我不想在两个地方维护,我相信一定有一种方法可以快速轻松地做到这一点,但我就是看不到。
有没有引用它的Style
中的按钮内容,或者我必须在该Buttons
ControlTemplate
中重建Path
,然后在这个新的ControlTemplate
中重新定义我的所有Triggers
?
转念一想,您不需要DataTrigger
。只需将2个Path
直接绑定到窗口状态即可。不过,您需要可重复使用的转换器。
下面是一个演示(使按钮可点击并将绑定添加到Fill
):
xaml:
<Button>
<Grid Width="10"
Height="10">
<Path Fill="Black"
Data="F1M0,0L0,9 9,9 9,0 0,0 0,3 8,3 8,8 1,8 1,3z"
Visibility="{Binding WindowState, RelativeSource=RelativeSource FindAncestor, AncestorType=Window}, ConverterParameter=Invert, Converter={local:StateToVisibilityConverter}}" />
<Path Fill="Black"
Data="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z"
Visibility="{Binding WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Converter={local:StateToVisibilityConverter}}" />
</Grid>
</Button>
转换器:
public class StateToVisibilityConverter : MarkupExtension, IValueConverter
{
public StateToVisibilityConverter() { }
public override object ProvideValue(IServiceProvider serviceProvider) => this;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var result = (WindowState)value == WindowState.Maximized;
if ((string)parameter == "Invert")
result = !result;
return result ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
}
第三个想法(仅xaml):
<Button>
<Path Fill="Black"
Width="10"
Height="10">
<Path.Style>
<Style TargetType="Path">
<Style.Setters>
<Setter Property="Data"
Value="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z" />
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Value="Maximized">
<Setter Property="Data"
Value="F1M0,0L0,9 9,9 9,0 0,0 0,3 8,3 8,8 1,1 1,3z" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
您可能需要一个ControlTemplate:
<Button
... [your other properties here] >
<Button.Template>
<ControlTemplate>
<Path x:Name="MaxPath"
Width="10"
Height="10"
Data="F1M0,0L0,9 9,9 9,0 0,0 0,3 8,3 8,8 1,8 1,3z"
SnapsToDevicePixels="True"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=WindowState}" Value="Minimised">
<Setter TargetName="MaxPath"
Property="Data"
Value="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
如果需要,可以添加其他触发器。。