Reputation: 1640
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?
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!
Upvotes: 0
Views: 741
Reputation: 483
Although this question already has an answer, I thought I would chip in since I have dealt with resizable controls myself. This is sort of a different approach since my controls have a much "cleaner" look. They rely on SVG data to make them resizable at will. The goal is high reusability and customizability, and it fits in very well with the current windows 10 look. Here is the GitHub: https://github.com/MarkoPaul0/PrettyNSharp
Upvotes: 0
Reputation: 16119
Just template it with a Grid. I've used flat colors to fill the rectangles in this example, just replace those with Image brushes that pull the pixels from the appropriate source rectangles in your image:
<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>
Result:
To be really honest though I think this is one of those cases where a custom UserControl might be in order, even if that control uses the same technique I've shown here. The exact point where each column and row is split will need to be referenced multiple times throughout your XAML, adding those points as dependency properties in a user control will make the code a lot more flexible and more easy customizable. To give you an idea of what I'm talking about here's what the first two rectangles might look like in XAML:
<Rectangle Grid.Row="0" Grid.Column="0">
<Rectangle.Fill>
<ImageBrush ImageSource="https://i.sstatic.net/something.jpg" Viewbox="0,0,100,100" ViewboxUnits="Absolute"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="0" Grid.Column="1">
<Rectangle.Fill>
<ImageBrush ImageSource="https://i.sstatic.net/something.jpg" Viewbox="100,0,1,100" ViewboxUnits="Absolute" TileMode="None"/>
</Rectangle.Fill>
</Rectangle>
Notice how "something.jpg" is reference in both rectangles. Templaing an Image instead of a UserControl will allow you to use a TemplateBinding to the Image source, but then there's still the issue of where to cut the rows and columns. You could do it with a combination of attached properties and converters but that's just getting silly. Create a custom user control and be done with it.
Upvotes: 1