自定义 WPF 可调整大小的按钮(以及可能的其他控件)

Custom WPF resizable buttons (and possibly other controls)

我一直在阅读有关更改 WPF 控件外观的内容。在大多数情况下,虽然按钮是从头开始创建的,因此没有多个来源,更不用说用于显示按钮的单个图像,但可以适当调整大小。

我想显示一个具有自定义外观的按钮。它应该能够从图像(最好是具有 per-pixel-alpha 的 PNG 图像)加载视觉数据,将其切成小块(请看下面的方案),从而正确调整按钮的大小,同时保持尽可能多的优点尽可能使用原始 WPF 按钮(包括文本/内容、图标、事件和绑定)。

这样的事情可能吗?

有没有一种 WPF 模板可以使用特定的图像源(如果需要,甚至可能是几个单独的文件)来允许可调整大小的按钮(或一般控件,如果可行的话)。这个按钮将包含一个图标和一些文本,它会有一个 "onMouseOver" 图像-"template" 以及一个 "onMouseDown" 图像。

我在 CSS 中知道这是可行的,让图像成为整个图像映射并使用坐标和剪裁矩形来确保正确的外观。有没有人知道这是否可行,并给我一些 指示,我可以在其中寻找如何 "design" 我自己的控件,这些控件源自已知的 ?

在这种特殊情况下,我真的需要按钮和可能的进度条。我想如果我能理解如何设置按钮和进度条的样式,我就会知道如何为其他类型的控件设置样式。

我正在使用 .NET Framework 4.5,将要使用此应用程序的人也必须使用相同的框架。

提前致谢!

只需使用网格对其进行模板化。在此示例中,我使用了纯色来填充矩形,只需将它们替换为图像画笔,这些图像画笔会从图像中的相应源矩形中提取像素:

<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Button.Template>
        <ControlTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="100"/>
                    <RowDefinition Height="1*"/>
                    <RowDefinition Height="50"/>
                    <RowDefinition Height="1*"/>
                    <RowDefinition Height="100"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"/>
                    <ColumnDefinition Width="1*"/>
                    <ColumnDefinition Width="50"/>
                    <ColumnDefinition Width="1*"/>
                    <ColumnDefinition Width="100"/>
                </Grid.ColumnDefinitions>
                <Rectangle Grid.Row="0" Grid.Column="0" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="0" Grid.Column="1" Fill="Yellow"/>
                <Rectangle Grid.Row="0" Grid.Column="2" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="0" Grid.Column="3" Fill="Yellow"/>
                <Rectangle Grid.Row="0" Grid.Column="4" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="1" Grid.Column="0" Fill="Green"/>
                <Rectangle Grid.Row="1" Grid.Column="4" Fill="Green"/>
                <Rectangle Grid.Row="2" Grid.Column="0" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="2" Grid.Column="4" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="3" Grid.Column="0" Fill="Green"/>
                <Rectangle Grid.Row="3" Grid.Column="4" Fill="Green"/>
                <Rectangle Grid.Row="4" Grid.Column="0" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="4" Grid.Column="1" Fill="Yellow"/>
                <Rectangle Grid.Row="4" Grid.Column="2" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="4" Grid.Column="3" Fill="Yellow"/>
                <Rectangle Grid.Row="4" Grid.Column="4" Fill="CornflowerBlue"/>
                <Rectangle Grid.Row="1" Grid.Column="1" Grid.RowSpan="3" Grid.ColumnSpan="3" Fill="Gray"/>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

结果:

老实说,我认为这是自定义 UserControl 可能是有序的情况之一,即使该控件使用我在此处展示的相同技术。在整个 XAML 中,需要多次引用每一列和每一行被拆分的确切点,将这些点添加为用户控件中的依赖属性将使代码更加灵活,更容易定制。为了让您了解我在说什么,这里是 XAML:

中前两个矩形的样子
<Rectangle Grid.Row="0" Grid.Column="0">
                    <Rectangle.Fill>
                        <ImageBrush ImageSource="http://i.stack.imgur.com/something.jpg" Viewbox="0,0,100,100" ViewboxUnits="Absolute"/>
                    </Rectangle.Fill>
                </Rectangle>
                <Rectangle Grid.Row="0" Grid.Column="1">
                    <Rectangle.Fill>
                        <ImageBrush ImageSource="http://i.stack.imgur.com/something.jpg" Viewbox="100,0,1,100" ViewboxUnits="Absolute" TileMode="None"/>
                    </Rectangle.Fill>
                </Rectangle>

请注意 "something.jpg" 在两个矩形中的引用方式。使用 Image 而不是 UserControl 模板化将允许您对 Image 源使用 TemplateBinding,但是仍然存在在何处剪切行和列的问题。您可以使用附加属性和转换器的组合来完成它,但这只是变得愚蠢。创建自定义用户控件并完成它。

虽然这个问题已经有了答案,但我想我会参与进来,因为我自己处理过可调整大小的控件。这是一种不同的方法,因为我的控件具有很多 "cleaner" 外观。他们依靠 SVG 数据使它们可以随意调整大小。目标是高可重用性和可定制性,并且非常适合当前的 windows 10 外观。这是 GitHub: https://github.com/MarkoPaul0/PrettyNSharp