XAML,在带动画的按钮内移动两个内容控件

时间:2017-07-30 23:03:58

标签: c# wpf visual-studio-2010 xaml

是否可以在按钮内移动两个内容控件并调整此按钮的大小?

<Button Height="100" Width="100">
  <Grid>
    <Grid.RowDefinitions>
       <RowDefinition height="30"/>
       <RowDefinition height="30"/>
    </Grid.RowDefinitions>
    <Image Grid.Row="0" Source="img.jpg"/>
    <TextBlock Grid.Row="1" Text="Some content"/>
  </Grid>
</Button>

我想在MouseOver上水平对齐它们而不是垂直对齐,并将按钮的大小从100调整到50,这可能吗?

2 个答案:

答案 0 :(得分:4)

这可以通过以下方式实现:

<Style x:Key="ExampleButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Height" Value="100"/>
    <Setter Property="Width" Value="100"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                    <UniformGrid x:Name="uGrid">
                        <Image Source="img.jpg" />
                        <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </UniformGrid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="false">
                        <Setter TargetName="uGrid" Property="Rows" Value="2" />
                        <Setter TargetName="uGrid" Property="Columns" Value="1" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="uGrid" Property="Columns" Value="2" />
                        <Setter TargetName="uGrid" Property="Rows" Value="1" />
                        <Setter Property="Height" Value="50" />
                        <Setter Property="Width" Value="50" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

此样式定义了按钮的修改模板,并可利用触发器响应鼠标事件。

要将样式添加到按钮,请执行以下操作:

<Grid>
    <Grid.Resources>
        <!-- Put Style Here -->
    </Grid.Resources>
    <Button Style="{DynamicResource ExampleButtonStyle}">
        <TextBlock Grid.Row="1" Text="Some content"/>
    </Button>
</Grid>

如何在样式和控件实例之间分发代码取决于您。您可能希望保持模块化和可重用性。

风格剖析

如果你以前没有探索过风格,那么它们可能会有点令人生畏和冗长。我已经解释了下面提供的样式的组件。

您可以通过声明样式来启动新样式。在这里,您必须指定一个目标类型(您要将样式应用于哪个)和一个Key(样式资源的名称:

<Style x:Key="ExampleButtonStyle" TargetType="{x:Type Button}">

    <!-- Style content goes here. -->

</Style>

Setter用于将样式应用值设置为目标控件的属性。例如:

    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Height" Value="100"/>
    <Setter Property="Width" Value="100"/>

因为您想要更改按钮的布局,所以您需要指定一个控件模板。为此,请使用Setter设置按钮的Template属性。此处的模板可以包含您想要的任何布局。 ContentPresenter用于显示实现中Button标签的主体:

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                    <UniformGrid x:Name="uGrid">
                        <Image Source="img.jpg" />
                        <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </UniformGrid>
                </Border>

                <ControlTemplate.Triggers>
                    <!-- Triggers here --> 
                </ControlTemplate.Triggers>                   

            </ControlTemplate>
        </Setter.Value>
    </Setter>

最后,您需要添加触发器以通过交互更新控件模板。触发器基本上观察控件的属性,并在其值与触发器指定的值匹配时应用。这会使用内部的setter更新控件。

<Trigger Property="IsMouseOver" Value="false">
    <Setter TargetName="uGrid" Property="Rows" Value="2" />
    <Setter TargetName="uGrid" Property="Columns" Value="1" />
</Trigger>

<强>布局

为了实现您的布局目标,我使用了UniformGrid。 UniformGrid将自身划分为相同的单元格以匹配其中的内容项数。请注意,这在WPF中可用,但不在UWP中。在UniformGrid上,您可以设置Columns或Rows计数,网格将根据需要进行补偿。在上面的样式中,我正在更改指定的行和列计数,并让网格相应地调整自身布局。这在视觉上将内容从行交换为列。

<强>关注

还有其他方法可以更优雅地实现这一目标,但Styles提供了大量的灵活性,并且具有较小的学习曲线。

你说你想把按钮大小从100改为50(我假设在两个轴上?)我必须建议你不要这样做。您将看到在应用提供的样式时会发生什么;按钮以100x100平方开始。用户将鼠标移到按钮上方,直到按钮边缘。按钮快速从50x50变为100x100,直到鼠标移动到中心或完全关闭按钮。这提供了一种糟糕且令人困惑的用户体验,值得更多考虑。

答案 1 :(得分:1)

这可能会迟到,但根据评论中的说法,这可以解决问题,我最近做过类似的事情

    <Style x:Key="btnSubMenu" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="White"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontSize" Value="20"/>
    <Setter Property="FontWeight" Value="ExtraBold"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                    <Grid x:Name="uGrid2">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="2*"/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Image Grid.Row="0" Source="/Images/1.png" />
                        <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <Grid Grid.Row="2" Name="Gbexample" Visibility="Collapsed">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="40"/>
                                <RowDefinition Height="40"/>
                                <RowDefinition Height="40"/>
                                <RowDefinition Height="40"/>
                            </Grid.RowDefinitions>
                            <Button Grid.Row="0" Style="{DynamicResource btnSubSubMenu}" Content="{DynamicResource strCity}" Name="btnCity"/>
                            <Button Grid.Row="1" Style="{DynamicResource btnSubSubMenu}" Content="{DynamicResource strCountry}" Name="btnCountry"/>
                            <Button Grid.Row="2" Style="{DynamicResource btnSubSubMenu}" Content="{DynamicResource strStore}" Name="btnStoreIn"/>
                            <Button Grid.Row="3" Style="{DynamicResource btnSubSubMenu}" Content="{DynamicResource strLocation}" Name="btnLocation"/>
                        </Grid>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="false">
                        <Setter TargetName="Gbproduct" Property="Visibility" Value="Collapsed" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="Gbproduct" Property="Visibility" Value="Visible" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>