开发者

In WPF, should my custom button with behaviour be an extended Button, a CustomControl, or just a ControlTemplate?

开发者 https://www.devze.com 2023-02-14 12:37 出处:网络
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 tas

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 Triggers 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 Buttons 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 Buttons 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 CustomControls, 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号