XAML,将两个ContentControl移动到一个带有动画效果的按钮内

4

是否可以将两个contentcontrol移动到一个按钮内,并调整该按钮的大小?

<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>

我希望在鼠标悬停时将它们水平对齐,而不是垂直对齐,并将按钮从100调整到50的大小,这可能吗?
2个回答

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>

你如何在样式和控件实例之间分发代码,取决于你。你可能希望保持模块化和可重用性。 样式的组成部分 如果你以前没有探索过样式,它们可能有点令人生畏和冗长。下面我解释了提供的样式组件。
你可以通过声明样式来开始一个新的样式。在这里,你必须指定目标类型(你想将样式应用到哪个对象)和键(样式资源的名称)。
<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上,您可以设置列或行计数,并根据需要进行调整。在上面的样式中,我更改了被提名的行和列计数,并让网格相应地调整其布局。这个视觉上将内容从行转换为列。

问题

还有其他方法可以更优雅地实现此操作,但样式提供了大量的灵活性,并且具有较小的学习曲线。

您指出您想将按钮大小从100更改为50(我假设在两个轴上都是),我必须劝您不要这样做。您将看到当应用提供的样式时会发生什么; 按钮开始作为一个100x100的正方形。用户将鼠标移动到按钮内部的位置后,按钮迅速从50x50更改为100x100,直到将鼠标移到中心或完全移出按钮。这会导致糟糕和混乱的用户体验,需要更多的思考。


没有评论!我不知道该如何感谢你,这太多了...无限感谢你。 - Erica Swan
关于按钮大小的问题,这是一个很好的点子,我会看看它是否会给用户带来麻烦,但我必须说我只是改变了高度而不是宽度,这是一种滑动菜单,一旦高度为50,一个折叠的网格将在空闲的50中升起...可能有点令人困惑^^" - Erica Swan
2
没问题。将折叠行为完全放入按钮中可能会更容易,这样相同的触发器可以将其“展开”。如果在按钮中,您可能可以避免快速更改的问题。虽然以网格为基础思考事物很容易,但您可能会发现通过更改其他属性来模拟相同的行为(例如 margin 和 padding)会更自由。例如,在某个东西下方显示网格可能类似于在下方添加一个 margin。随着 XAML 的增长,像这样的事情可以使其更易于阅读。即网格用于布局,而不是临时定位。 - Élie

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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接