如何从WPF中的样式ControlTemplate引用父控件?

时间:2010-06-30 21:15:04

标签: wpf

我有一个简单的标签控件样式。我想在样式中使用按钮定义一个控件模板,可以单击该按钮并将标签的visibility属性设置为“Hidden”。像这样:

<Style x:Key="MessageLabel_WithCloseButton" TargetType="{x:Type Label}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Label}">
                <Border BorderThickness="1" Padding="4" CornerRadius="3"   
                        BorderBrush="Gray" Background="#FFA11616">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <ContentPresenter Grid.Column="0"/>
                        <Button Grid.Column="1" Width="16" Height="16" Padding="2" FontSize="9" Content="X">
                       <!-- THIS IS WRONG! HOW TO CREATE A TRIGGER FOR THIS BUTTON 
                            HERE AND HOW TO REFER TO THE LABEL? -->
                            <Button.Triggers>

                                <Trigger Property="Button.IsPressed" Value="True">
                                    <Setter Property="Visibility" Value="Hidden" />
                                </Trigger>
                            </Button.Triggers>
                        </Button>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

问题是我不知道如何使用触发器处理点击,以及如何设置包含按钮的标签的属性。

感谢。

2 个答案:

答案 0 :(得分:2)

我使用Blend 4创作了这个。基本上你想要用EventTrigger处理按钮上的“PreviewMouseButtonUp”事件。 EventTrigger将启动Storyboard,将视觉树顶部的UIElement.Visibility属性设置为“隐藏”,以获得标签的样式。

要控制按钮中的内容,可以使用标签控件上的Tag属性。否则,您将不得不创建另一个依赖项属性,这意味着继承Label

在样式中,<Button/>看起来像这样:

<Button x:Name="button" Grid.Column="1" Padding="2" 
  FontSize="9" 
  Content="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"/>

...因为您可以将任何内容放入Tag属性中,您可以执行此操作:

    <Label x:Name="label" Content="Label" 
      Style="{DynamicResource MessageLabel_WithCloseButton}">
        <Label.Tag>
            <StackPanel>
                <TextBlock>WOOT</TextBlock>
                <TextBlock>WOOT</TextBlock>
            </StackPanel>
        </Label.Tag>
    </Label>

这是一个修改过的完整样式(我还修改了一些东西以便更好地自动调整大小:

    <Style x:Key="MessageLabel_WithCloseButton" TargetType="{x:Type Label}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="OnClick1">
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="border">
                                <DiscreteObjectKeyFrame KeyTime="0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <Visibility>Hidden</Visibility>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Border x:Name="border" BorderThickness="1" Padding="4" CornerRadius="3"   
                    BorderBrush="Gray" Background="#FFA11616">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <ContentPresenter Grid.Column="0" VerticalAlignment="Center" Margin="0,0,3,0"/>
                            <Button x:Name="button" Grid.Column="1" Padding="2" FontSize="9" Content="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="UIElement.PreviewMouseLeftButtonUp" SourceName="button">
                            <BeginStoryboard x:Name="OnClick1_BeginStoryboard" Storyboard="{StaticResource OnClick1}"/>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

另请注意,EventTrigger位于您的ControlTemplate上,而不在您树中的Button上。但这可能只是Blend生成代码的方式。

答案 1 :(得分:1)

你可以使用ToggleButton而不是普通的Button,然后只使用Trigger的IsChecked属性:

<Style x:Key="MessageLabel_WithCloseButton" TargetType="{x:Type Label}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Label}">
                <Border BorderThickness="1" Padding="4" CornerRadius="3"   
                BorderBrush="Gray" Background="#FFA11616">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <ContentPresenter Grid.Column="0"/>
                        <ToggleButton x:Name="CloseButton" Grid.Column="1" Width="16" Height="16" Padding="2" FontSize="9" Content="X"/>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger SourceName="CloseButton" Property="IsChecked" Value="True">
                        <Setter Property="Visibility" Value="Hidden" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>