Custom WPF resizable buttons (and possibly other controls)

时间:2015-07-29 00:45:13

标签: wpf wpf-controls wpf-style

I have been reading about changing the appearance of WPF controls. In most cases though the buttons were created from scratch and thus there were no multiple sources let alone one single image used to display a button, that would properly resize.

I want to display a button, which has a custom look to it. It should be able to load the visual data from an image (preferably PNG-image with per-pixel-alpha), slice it into pieces (please look at the scheme below) and thus resize the button correctly, while keeping as many advantages of the original WPF Button (including text / content, icons, events and binding) as possible.

Is something like this possible?

enter image description here

Is there a way to have a WPF template, that would use a certain imagesource (or perhaps even several separate files if need be) to allow a resizable button (or control in general if this is do-able). This button would contain an icon and some text and it would have an "onMouseOver" image-"template" as well as a "onMouseDown" one.

I know in CSS this is do-able having an image be a whole image-map and use coordinates and clipping rectangles to ensure proper appearance. Does anyone have an idea if this is possible and give me some pointers where I could look for how to "design" my own controls, that derive from known ones?

In this particular case I really need buttons and possibly progress bars. I think if I could understand how to style buttons and progress bars, I would have an idea on how to go about it for other types of controls.

I am using .NET Framework 4.5 and the people, who will be using this application, will have to use the same framework as well.

Thank you in advance!

2 个答案:

答案 0 :(得分:1)

使用网格模板化。我在这个例子中使用了平面颜色来填充矩形,只需用图像画笔替换那些从图像中适当的源矩形拉出像素的图像:

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

结果:

enter image description here

说实话虽然我认为这是自定义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”是如何引用的。模板化而不是UserControl将允许您使用TemplateBinding到Image源,但是仍然存在切割行和列的位置的问题。你可以通过附加属性和转换器的组合来实现它,但这只是变得愚蠢。创建自定义用户控件并完成它。

答案 1 :(得分:0)

虽然这个问题已经有了答案,但我认为自从我自己处理可调整大小的控件后,我会填补这个问题。这是一种不同的方法,因为我的控件具有更“清洁”的外观。他们依靠SVG数据使它们随意调整大小。目标是高可重用性和可定制性,并且它非常适合当前的Windows 10外观。这是GitHub: https://github.com/MarkoPaul0/PrettyNSharp