如何在XAML中访问父模板样式的元素?

时间:2017-08-14 14:06:01

标签: c# wpf xaml

我无法在WPF中访问父模板样式的命名元素。

我有一个按钮的自定义控件(按this StackOverflow question编写):

CustomButton.xaml:

<ResourceDictionary ...>
<Style x:Key="ButtonCustomStyle" TargetType="{x:Type local:ImageButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ImageButton}">
                <Grid>
                    <Image Source="{TemplateBinding Image}" Stretch="Fill" x:Name="CurrentImage"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="CurrentImage" Property="Source" Value="{Binding ImageHover, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MainWindow.xaml:

<Window ...>
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="CustomButton.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="{x:Type local:ImageButton}" BasedOn="{StaticResource ButtonCustomStyle}"/>
    </ResourceDictionary>
</Window.Resources>

<Grid>
    <local:ImageButton Image="\Images\image.png" ImageHover="\Images\image_hover.png" Width="20" Height="20"/>
</Grid>

ImageButton继承ButtonImageImageHover被定义为依赖项属性。这段代码效果很好,并且可以达到预期效果。

现在,我想为单个特定按钮扩展此模板样式,添加一个额外的Trigger来更改按钮的图像。我正在尝试执行以下操作:

<Window...>
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="CustomButton.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="{x:Type local:ImageButton}" BasedOn="{StaticResource ButtonCustomStyle}"/>
        <Style TargetType="{x:Type local:ImageButton}"
               BasedOn="{StaticResource ButtonCustomStyle}"
               x:Key="Disableable">
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter TargetName="CurrentImage" Property="Source" Value="\Images\disabled.png"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ResourceDictionary>
</Window.Resources>

<Grid>
    <local:ImageButton Image="\Images\image.png" ImageHover="\Images\image_hover.png" Width="20" Height="20"/>
    <local:ImageButton Style="{StaticResource Disableable}" Image="\Images\image.png" ImageHover="\Images\image_hover.png" Width="20" Height="20"/>
</Grid>

但Visual Studio强调了新的setter行,并说'The name "CurrentImage" is not recognized'

有没有办法改变CurrentImage元素?

2 个答案:

答案 0 :(得分:1)

与ControlTemplete触发器不同,Style触发器无权访问模板元素。因为您公开了Image属性,所以在Style trigger setter:

中使用它
<Trigger Property="IsEnabled" Value="False">
    <Setter Property="Image" Value="\Images\disabled.png"/>
</Trigger>

答案 1 :(得分:1)

  

我无法在WPF中访问父模板样式的命名元素。

这是不可能的。您无法将ControlTemplate基于另一个ControlTemplate

如果您希望setter能够找到定义的ControlTemplate元素,我恐怕您必须在派生的Style中从头开始重新定义整个CurrentImage基础Style的模板。

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

但是,您应该能够使用ControlTemplate触发器设置控件本身的Style属性,而不是设置Image,而不是使用Source触发器。模板中Image元素的属性:

<Style x:Key="ButtonCustomStyle" TargetType="{x:Type local:ImageButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ImageButton}">
                <Grid>
                    <Image Source="{TemplateBinding Image}" Stretch="Fill" x:Name="CurrentImage"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Image" Value="{Binding ImageHover, RelativeSource={RelativeSource Self}}"/>
        </Trigger>
    </Style.Triggers>
</Style>

<Style TargetType="{x:Type local:ImageButton}"
               BasedOn="{StaticResource ButtonCustomStyle}"
               x:Key="Disableable">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Image" Value="\Images\disabled.png"/>
        </Trigger>
    </Style.Triggers>
</Style>