如何在网格中添加多个自定义形状的按钮?

时间:2019-11-08 10:21:52

标签: c# wpf

我需要在一个圆圈中创建4个按钮。

每个蓝色按钮可以单独控制:

enter image description here

我已经使用.xaml中的CombinedGeometry为按钮制作了一个ControlTemplate,并将此模板分配给了按钮。 我的代码的.xaml文件如下:

<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="450">
<Window.Resources>
    <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}" >
        <Grid>
            <Path Name="Border" Stroke="Black" StrokeThickness="1" Stretch="Fill">
                <Path.Data>
                    <CombinedGeometry GeometryCombineMode="Exclude">
                        <CombinedGeometry.Geometry1 >
                            <CombinedGeometry GeometryCombineMode="Exclude">
                                <CombinedGeometry.Geometry1 >
                                    <CombinedGeometry GeometryCombineMode="Exclude">
                                        <CombinedGeometry.Geometry1 >
                                            <CombinedGeometry GeometryCombineMode="Exclude">
                                                <CombinedGeometry.Geometry1>
                                                    <EllipseGeometry Center="50 50" RadiusX="100" RadiusY="100"></EllipseGeometry>
                                                </CombinedGeometry.Geometry1>
                                                <CombinedGeometry.Geometry2>
                                                    <EllipseGeometry Center="50 50" RadiusX="60" RadiusY="60"></EllipseGeometry>
                                                </CombinedGeometry.Geometry2>
                                            </CombinedGeometry>
                                        </CombinedGeometry.Geometry1>
                                        <CombinedGeometry.Geometry2>
                                            <RectangleGeometry Rect="50,-50 40,200">
                                                <RectangleGeometry.Transform>
                                                    <RotateTransform Angle="45" CenterX="50" CenterY="50"/>
                                                </RectangleGeometry.Transform>
                                            </RectangleGeometry>
                                        </CombinedGeometry.Geometry2>

                                    </CombinedGeometry>
                                </CombinedGeometry.Geometry1>
                                <CombinedGeometry.Geometry2>
                                    <RectangleGeometry Rect="50,-50 40,200">
                                        <RectangleGeometry.Transform>
                                            <RotateTransform Angle="135" CenterX="50" CenterY="50"/>
                                        </RectangleGeometry.Transform>
                                    </RectangleGeometry>
                                </CombinedGeometry.Geometry2>
                            </CombinedGeometry>
                        </CombinedGeometry.Geometry1>
                        <CombinedGeometry.Geometry2>
                            <RectangleGeometry Rect="-50,10 200,140">
                            </RectangleGeometry>
                        </CombinedGeometry.Geometry2>
                    </CombinedGeometry>
                </Path.Data>
            </Path>
            <Rectangle Name="FocusCue" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2" SnapsToDevicePixels="True" ></Rectangle>
            <Border>
                <ContentPresenter  Name="Content" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" TextBlock.Foreground="White"></ContentPresenter>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="Border" Property="Fill" Value="DarkRed" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</Window.Resources>

<Grid>
    <Grid Width="200" Height="85">
        <Button Template="{StaticResource ButtonTemplate}" Margin="-48,-75,48,75">
        </Button>
    </Grid>
    <Grid Width="200" Height="85">
        <Button Template="{StaticResource ButtonTemplate}" Margin="-97,176,97,-176">
            <Button.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="270"/>
                </TransformGroup>
            </Button.RenderTransform>
        </Button>
    </Grid>
    <Grid Width="200" Height="85">
        <Button Template="{StaticResource ButtonTemplate}" Margin="203,-25,-203,25">
            <Button.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="90"/>
                </TransformGroup>
            </Button.RenderTransform>
        </Button>
    </Grid>
    <Grid Width="200" Height="85">
        <Button Template="{StaticResource ButtonTemplate}" Margin="152,225,-152,-225">
            <Button.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="180"/>
                </TransformGroup>
            </Button.RenderTransform>
        </Button>
    </Grid>
</Grid>
</Window>

当前结果:

enter image description here

我使用CombinedGeometry和指定的边距来定位按钮。

我的问题是,应该使用哪个容器将这些按钮放在一起?

如何避免指定的边距?

编辑:

bacon的当前结果

enter image description here

我在原始路径上添加了一个黑色箭头。

我想触发一个触发器,以同时更改这两条路径的不同颜色。

这就是我现在拥有的:

<ControlTemplate>
<Grid>

<Path><!-- original path --></Path>

<Path Stroke="Transparent" Width="100" Height="100">
    <Path.Data>
        <PathGeometry>
            <PathFigure IsClosed="True"  StartPoint="43,43">
                <LineSegment Point="57,57" />
                <LineSegment Point="60,40" />
            </PathFigure>
        </PathGeometry>
    </Path.Data>
    <Path.Style>
    <Style TargetType="{x:Type Path}">
        <Setter Property="Fill" Value="Black"/>
        <!-- only change the color of arrow
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Fill" Value="#3B3B3B"/>
            </Trigger>
        </Style.Triggers>
        -->
    </Style>
    </Path.Style>
</Path>
</Gird>

<!-- change both paths with Opacity
<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Opacity" Value="0.5"/>
    </Trigger>
</ControlTemplate.Triggers>
-->

</ControlTemplate>

1 个答案:

答案 0 :(得分:3)

我使用rendertransformorgin重新创建了示例,因此可以简化操作,可以使用视图框包含按钮

编辑:如您的帖子评论中所述 我将按钮模板创建为四分之一圆,并在左下角进行了切割。然后以90度为增量旋转按钮以闭合圆,然后将整个圆旋转45度

我还添加了一个鼠标悬停,因此按钮变为红色(我需要检查一下,鼠标悬停是否注册了整个封闭的矩形,或者只是形状->鼠标悬停仅在形状上触发)

SharedSizeGroup使得2 x 2网格我使用正方形,并且视图框将内容缩放为适合的大小

<Window.Resources>
    <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}" >
        <Path Name="Border" Stroke="Black" Width="100" Height="100">
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True" StartPoint="10 10" >
                        <ArcSegment Point="90 90" Size="85 85" IsLargeArc="false" SweepDirection="Clockwise" />
                        <LineSegment Point="60 90" ></LineSegment>
                        <ArcSegment Point="10 40" Size="55 55" IsLargeArc="false" SweepDirection="Counterclockwise" />
                        <LineSegment Point="10 10" ></LineSegment>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
            <Path.Style>
                <Style TargetType="{x:Type Path}">
                <Setter Property="Fill" Value="Green"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Fill" Value="Red"/>
                    </Trigger>
                </Style.Triggers>
                </Style>
            </Path.Style>
        </Path>
    </ControlTemplate>
</Window.Resources>
<Grid Margin="10px">
    <Viewbox>
        <Grid RenderTransformOrigin="0.5,0.5" Grid.IsSharedSizeScope="True">
            <Grid.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="45"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Grid.RenderTransform>
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="A"/>
                <ColumnDefinition SharedSizeGroup="A"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition SharedSizeGroup="A"/>
                <RowDefinition SharedSizeGroup="A"/>
            </Grid.RowDefinitions>
            <Button Template="{StaticResource ButtonTemplate}" Grid.Column="0" Grid.Row="0" RenderTransformOrigin="0.5,0.5">
                <Button.RenderTransform>
                    <RotateTransform Angle="270"/>
                </Button.RenderTransform>
            </Button>
            <Button Template="{StaticResource ButtonTemplate}" Grid.Column="1" Grid.Row="0" RenderTransformOrigin="0.5,0.5">
            </Button>
            <Button Template="{StaticResource ButtonTemplate}" Grid.Column="0" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
                <Button.RenderTransform>
                    <RotateTransform Angle="180"/>
                </Button.RenderTransform>
            </Button>
            <Button Template="{StaticResource ButtonTemplate}" Grid.Column="1" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
                <Button.RenderTransform>
                    <RotateTransform Angle="90"/>
                </Button.RenderTransform>
            </Button>
        </Grid>
    </Viewbox>
</Grid>

should look like this

编辑: 如您所见,将触发器置于分开的波西形状上可以改变颜色

    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=IsMouseOver}" Value="True">

这是完整的代码:

    <Window.Resources>
    <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}" >
        <Grid>

        <Path Name="Border" Stroke="Black" Width="100" Height="100">
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True" StartPoint="10 10" >
                        <ArcSegment Point="90 90" Size="85 85" IsLargeArc="false" SweepDirection="Clockwise" />
                        <LineSegment Point="60 90" ></LineSegment>
                        <ArcSegment Point="10 40" Size="55 55" IsLargeArc="false" SweepDirection="Counterclockwise" />
                        <LineSegment Point="10 10" ></LineSegment>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
            <Path.Style>
                <Style TargetType="{x:Type Path}">
                    <Setter Property="Fill" Value="Gray"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=IsMouseOver}" Value="True">
                                <Setter Property="Fill" Value="LightGray"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Path.Style>
        </Path>
            <Path Stroke="Transparent" Width="100" Height="100">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure IsClosed="True"  StartPoint="43,43">
                            <LineSegment Point="57,57" />
                            <LineSegment Point="60,40" />
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
                <Path.Style>
                    <Style TargetType="{x:Type Path}">
                        <Setter Property="Fill" Value="Black"/>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=IsMouseOver}" Value="True">
                                <Setter Property="Fill" Value="DimGray"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Path.Style>
            </Path>
        </Grid>
    </ControlTemplate>
</Window.Resources>
<Grid Margin="10px">
    <Viewbox>
        <Grid>
            <Grid RenderTransformOrigin="0.5,0.5" Grid.IsSharedSizeScope="True">
                <Grid.RenderTransform>
                    <TransformGroup>
                        <RotateTransform Angle="45"/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Grid.RenderTransform>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="A"/>
                    <ColumnDefinition SharedSizeGroup="A"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition SharedSizeGroup="A"/>
                    <RowDefinition SharedSizeGroup="A"/>
                </Grid.RowDefinitions>
                <Button Template="{StaticResource ButtonTemplate}" Grid.Column="0" Grid.Row="0" RenderTransformOrigin="0.5,0.5">
                    <Button.RenderTransform>
                        <RotateTransform Angle="270"/>
                    </Button.RenderTransform>
                </Button>
                <Button Template="{StaticResource ButtonTemplate}" Grid.Column="1" Grid.Row="0" RenderTransformOrigin="0.5,0.5">
                </Button>
                <Button Template="{StaticResource ButtonTemplate}" Grid.Column="0" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
                    <Button.RenderTransform>
                        <RotateTransform Angle="180"/>
                    </Button.RenderTransform>
                </Button>
                <Button Template="{StaticResource ButtonTemplate}" Grid.Column="1" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
                    <Button.RenderTransform>
                        <RotateTransform Angle="90"/>
                    </Button.RenderTransform>
                </Button>
            </Grid>
            <TextBlock Background="{x:Null}" HorizontalAlignment="Center" VerticalAlignment="Center">Content</TextBlock>
        </Grid>
    </Viewbox>
</Grid>

With ColorChanging Arrows