In WPF, should my custom button with behaviour be an extended Button, a CustomControl, or just a ControlTemplate?
I have a ControlTemplate
for typeButton
that imitates the Windows 7 taskbar button style. I can apply this to a standard Button
and it looks just right. For those that have not seen Windows 7, the taskbar buttons also have a behaviour... a glow appears when you mouse over the buttons and it moves horizontally as you move your mouse over it.
So I replicated this behaviour by extending Button
in two stages; first in xaml, I used Trigger
s to fade in the Opacity
of my 'glow' RadialGradientBrush
using the MouseEnter
event and fade it out again using the MouseLeave
event; then in the code behind, I implemented a MouseMove
event handler to move the RadialGradientBrush.GradientOrigin
and RadialGradientBrush.Center
properties to the current mouse position. All lovely. However, I am always trying to improve my code as I learn more about WPF and I am curious about a few things.
Ok, so here are the questions...
Firstly, I am aware that there is nothing built into WPF that will give me access to the current mouse position in xaml, but is there something that I can do to get it? By that I mean something like adding a class as an ObjectDatProvider
in Resources
that exposes the current mouse position as a DependencyProperty
that I can bind directly to the Center
and GradientOrigin
properties of the RadialGradientBrush
.
I'm clutching at straws here... The aim is to remove the code behind if possible so I can just use a ControlTemplate
to Style
all Button
s in the application. Or is right that this behaviour should be in code behind in WPF?
Secondly, if it really is better to use code behind for the behaviour in my custom Button
, then is it better to create a CustomControl
, or to leave it as it currently is, extending Button
?
Finally, if it stays as an extended Button
, is it possible to make it replace the normal Button
Style
? I'm thinking of the way that defining a Style
in Resources
with a TargetType
property set, but no x:key
property set will automatically set all of that type of Control
to that Style
... some way of saying that if any Button
s are in the application, they should be this type of Button
. Again, clutching at straws, but there no harm in asking.
EDIT >>>
Here is the xaml in my extended Button
control (minus Resources
):
<Button.Template>
<ControlTemplate>
<Grid MouseMove="Button_MouseMove">
<Border CornerRadius="3" BorderBrush="#7E000000" BorderThickness="1" Background="#7EFFFFFF">
<Grid Margin="1">
<Rectangle x:Name="BackgroundRectangle" RadiusX="1.5" RadiusY="1.5" StrokeThickness="0" Fill="{StaticResource Windows7Background}" />
<Rectangle x:Name="Glow" IsHitTestVisible="False" RadiusX="1.5" RadiusY="1.5" StrokeThickness="0" Opacity="0.0" Fill="{StaticResource GlowBrush}" />
<ContentPresenter RecognizesAccessKey="True" ManyManyProperties="{TemplateBinding}"... /&g开发者_JAVA技巧t;
</Grid>
</Border>
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Glow" Storyboard.TargetProperty="Opacity" From="0.0" To="1.0" Duration="0:0:0.5" DecelerationRatio="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Glow" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:1" DecelerationRatio="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
</Grid>
</ControlTemplate>
</Button.Template>
Have you thought about using an attached behavior/property instead of extending the button control? You have probably used attached properties without knowing it, things like Grid.Row, and DockPanel.Dock.
Basically that just means that you want to add a chunk of logic to an existing control. For instance in this example, the user can provide a brush to the control through the attached property.
<Button Content="Button 1" local:Hover.Brush="Red" />
The attached property, is basically a static class with a DependencyProperty. In your case it reacts to the mouse events, and sets the background brush accordingly. In fact the attached property doesn't even have to care that the control is a button, just a Control which has access to MouseEnter, MouseLeave and MouseMove.
In your global button style you can the attached property as follows:
<Setter Property="local:Hover.Brush" Value="Red" />
You can pass your radial brush from a resource as well, so that if you want to change the color scheme you won't have to change the behavior, just the resources.
More on behaviors...
Attached behaviors are basically the same kind of thing. You can see an article by Josh Smith (the expert on all things WPF) here so you can get an even better idea of what other kinds of things you can do with attached behaviors/properties.
Edit: I reviewed your post again and realized that it is not the background color you want to change, but the brush on the shine. I'll try and update my answer with more details soon.
After reading the relevant chapters in Sells & Griffiths' Programming WPF book (an excellent book), I think I can now answer my own question. According to these guys, a UserControl
is "intended to offer a similar functionality to user controls in other UI frameworks". By this, they mean a user control as a kind of invisible panel that contains a collection of controls, such as a particular form. One further note is that they "do not usually support customization through templates".
Regarding CustomControl
s, they say "the role of a [custom] control is to define essential behaviour... if the behaviour you require is not provided by any existing controls and you cannot create it by bolting a few controls together, you will need to write a custom control".
Further advice is that a "control may provide a default set of visuals, but it should allow these to be replaced in order to offer the same flexibility as the built-in controls... A control that conforms to this approach, where the visuals are separated from the control, is often described as lookless... All of the controls built into WPF are lookless".
Going by this advice, I think that I will create a new CustomControl
for my 'glow Button
', with a default ControlTemplate
and Style
. This way, I'll be able to change the style of the Button
, but keep the glowing mouse over effect over the top.
精彩评论