WPF Setter Target绑定到按钮内容的名称

时间:2015-11-27 11:39:38

标签: c# wpf wpf-controls

我已经为窗口中的所有按钮构建了一个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内的按钮内容,或者我必须重新构建Path Buttons内的ControlTemplate,然后重新定义所有内容我的Triggers在这个新的ControlTemplate

2 个答案:

答案 0 :(得分:1)

从第二个想法开始,你不需要DataTrigger。只需将2 Path直接绑定到窗口状态即可。您需要可重复使用的转换器。

下面是一个演示(make按钮可点击并添加到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>

答案 1 :(得分:0)

您可能需要一个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>

如果您愿意,可以添加其他触发器。