WPF Custom Controller Button

Brandon Boone 21 Reputation points
2021-05-05T21:49:37.267+00:00

I am making a button, but I do not know how to make it anime a click action.

here is my code:

<UserControl x:Class="HMIButtonControl.SaveButton"  
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
             xmlns:local="clr-namespace:HMIButtonControl"  
             xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"  
             mc:Ignorable="d"   
             d:DesignHeight="450" d:DesignWidth="800">  
  
    <Viewbox>  
        <Canvas Height="40" Width="100">  
            <Rectangle Canvas.Left="0" Canvas.Top="0" Height="40" Width="40" StrokeThickness="0.5" Stroke="Gray" RadiusX="5" RadiusY="5">  
                <Rectangle.Fill>  
                    <LinearGradientBrush x:Name="LinearProcessBrush" StartPoint="0.5,0.5" EndPoint="1,0" SpreadMethod="Pad">  
                        <GradientStop Color ="Black" Offset="0"/>  
                        <GradientStop Color="Gray" Offset ="2" />  
                    </LinearGradientBrush>  
                </Rectangle.Fill>  
            </Rectangle>  
  
  
            <Rectangle Canvas.Left="4" Canvas.Top="5" Height="32" Width="32" StrokeThickness="0" Stroke="Gray" RadiusX="3.5" RadiusY="3.5">  
                <Rectangle.Fill>  
                    <LinearGradientBrush x:Name="LinearProcessBrush2" StartPoint="0,0.5" EndPoint="0,1" SpreadMethod="Pad">  
                        <GradientStop Color ="Black" Offset="0"/>  
                        <GradientStop Color="Gray" Offset ="2" />  
                    </LinearGradientBrush>  
                </Rectangle.Fill>  
            </Rectangle>  
  
  
            <Viewbox Height="4" Width="1"  Margin="-5,-4,0,0" >  
        <Canvas Height ="25" Width="100">  
  
            <Canvas Name="g8" >  
                <Path  Name="path4" Fill="#FFFFFFFF" Data="m 1396 2749.6 0.7 -513.8 5.1 -13.6 c 8.6 -22.7 19.4 -39.3 36 -55.6 16.4 -16.1 38.1 -28.3 61.7 -35.1 17.3 -4.9 1658.2 -4.9 1676 0 45.6 12.6 80.2 44.6 97.7 90.7 l 5.1 13.6 0.7 513.8 0.5 513.5 h -942 -942 z m 1698.9 179.3 v -28 h -757.3 -757.3 v 28 28 h 757.3 757.3 z m 0 -209.2 v -26.9 h -757.3 -757.3 v 26.9 26.9 h 757.3 757.3 z m 0 -209.2 v -28 h -757.3 -757.3 v 28 28 h 757.3 757.3 z"/>  
                <Path  Name="path6" Fill="#FFFFFFFF" Data="m 1882.9 1934 c -48.4 -7.7 -89.8 -45.8 -105.9 -97.9 -3 -10.3 -3.7 -57 -4.4 -396.7 l -1.2 -385.2 h 605.6 605.6 v 385.2 c 0 320.7 -0.7 386.9 -3.3 395.5 -13.3 43.2 -46.8 77.6 -91.4 93.5 l -14 4.9 -492 0.9 c -270.7 0.5 -495.1 0.2 -499.1 -0.2 z M 2787 1802.6 c 14.7 -5.4 31.6 -20.3 40.2 -35.8 l 7 -12.6 v -259.5 -259.5 l -6.3 -12.2 c -7.5 -14 -20.3 -27.1 -33.4 -34.4 -9.4 -4.9 -10.5 -4.9 -148.4 -4.9 H 2507 l -12.4 7.7 c -14.7 8.9 -21.7 16.4 -30.4 32 l -6.3 11.7 0.2 258.3 0.2 258.3 5.4 11.5 c 7.2 16.1 24.3 32.5 40 38.3 12.2 4.7 16.4 4.9 142.4 4.9 115.2 -0.2 130.9 -0.5 141 -4 z"/>  
            </Canvas>  
            <Canvas Name="g14">  
                 
                <Path  Name="path10" Fill="#FF5B6E80" Data="m 1217.8 3596.2 c -77.8 -14.7 -142.1 -69.7 -167.4 -142.8 -11.9 -34.6 -11.2 47.5 -11.9 -1186 -0.9 -1065.9 -0.7 -1145.6 3 -1164.1 14.5 -73.9 70.6 -138.8 140 -162.7 35.8 -12.2 -40 -11.2 982.9 -11.9 858.1 -0.7 947.2 -0.5 963 2.8 17.8 4 35.5 9.4 52.6 16.4 46.3 18.9 44.6 17.3 246.8 220.2 178.6 178.8 184.2 184.7 192.1 201.7 4.7 9.6 10.3 25.5 12.6 35.1 4 16.8 4.2 60.3 4.2 1014.5 v 996.9 l -5.4 19.9 c -10.3 38.8 -29.9 72.5 -59.1 100.7 -26.2 25.5 -55.4 42.5 -92.8 54.2 -15.4 4.7 -20.8 4.9 -286.8 6.5 -149.1 0.7 -650.8 1.6 -1115 1.6 -659.2 0 -847.1 -0.7 -859 -3 z m 2049.5 -218.6 c -0.5 -96.8 0 -121.6 2.3 -121.6 2.3 0 2.8 -99.8 2.3 -506.5 l -0.7 -506.8 -5.1 -13.6 c -17.5 -46 -52.1 -78.1 -97.7 -90.7 -17.8 -4.9 -1644.7 -4.9 -1662 0 -46 13.1 -80.2 44.6 -97.7 90.7 l -5.1 13.6 -0.7 506.8 c -0.5 407.2 0 506.5 2.3 506.1 2.3 -0.5 3.3 24.5 3.7 121.6 l 0.5 122 H 2338.6 3268 Z M 2880.9 1921.3 c 44.6 -15.9 78.1 -50.3 91.4 -93.5 2.6 -8.6 3.3 -73.9 3.3 -388.5 V 1061.1 H 2377 1778.4 l 1.2 378.2 c 0.9 405.8 0.2 383.1 12.2 410.7 5.6 13.1 24.8 38.3 35.8 47.2 19.2 15.4 42.3 26.4 62.4 29.7 4 0.5 225.3 0.7 492 0.2 l 485 -0.9 14 -4.9 z"/>  
                <Path  Name="path12" Fill="#FF5B6E80" Data="m 2496.7 1808.8 c -15.7 -5.8 -32.7 -22.2 -40 -38.3 l -5.4 -11.5 -0.2 -265.3 -0.2 -265.3 6.3 -11.7 c 8.6 -15.7 15.7 -23.1 30.4 -32 l 12.4 -7.7 h 146.1 c 144.9 0 146.1 0 155.4 4.9 13.1 7.2 25.9 20.3 33.4 34.4 l 6.3 12.2 v 266.5 266.5 l -7 12.6 c -3.7 7 -11.9 16.8 -18 22.2 -20.8 17.8 -16.4 17.3 -170.2 17.5 -133 0 -137 -0.2 -149.4 -4.9 z"/>  
            </Canvas>  
            <Canvas Name="g18"  >  
                  
                <Path Name="path16" Fill="#FF97D5C9" StrokeThickness="1" Data="m 1403 3380.7 c 0.5 -69.2 1.4 -125.5 2.6 -125.1 0.9 0.2 421.9 0.5 935.5 0.5 h 933.8 v 125.1 125.1 h -936.2 -936.2 l 0.5 -125.5004 z"/>  
            </Canvas>  
            <Canvas Name="g26"   >  
                <Path Name="path20" Fill="#FF5BC1AC" Data="m 1573.1 2928.9 v -35.1 h 764.4 764.4 v 35.1 35.1 h -764.4 -764.4 z"/>  
                <Path Name="path22" Fill="#FF5BC1AC" Data="m 1573.1 2719.7 v -33.9 h 764.4 764.4 v 33.9 33.9 h -764.4 -764.4 z"/>  
                <Path Name="path24" Fill="#FF5BC1AC" Data="m 1573.1 2510.5 v -35.1 h 764.4 764.4 v 35.1 35.1 h -764.4 -764.4 z"/>  
            </Canvas>  
        </Canvas>  
    </Viewbox>  
        </Canvas>  
    </Viewbox>  
</UserControl>  

I wanted it to look and work like the once on Audacity but I could not get it:
94114-image.png

Can anyone help me?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,671 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,238 questions
0 comments No comments
{count} votes

Accepted answer
  1. Emon Haque 3,176 Reputation points
    2021-05-05T22:22:16.233+00:00

    Create one Button like this:

    class ActionButton : FrameworkElement  
    {  
        Border border;  
        string icon;  
        public string Icon {  
            get { return icon; }  
            set { icon = value; ((Path)border.Child).Data = Geometry.Parse(value); }  
        }  
        public Action Command { get; set; }  
        protected SolidColorBrush brush;  
        protected ColorAnimation anim;  
        protected Color normalColor, highlightColor, downColor;         
        public ActionButton() {  
            normalColor = Colors.Black;  
            highlightColor = Colors.Coral;  
            downColor = Colors.Red;  
            brush = new SolidColorBrush(normalColor);  
            border = new Border() {  
                Background = Brushes.Transparent,  
                Child = new Path() {  
                    Fill = brush,  
                    Stretch = Stretch.Uniform  
                }  
            };  
            anim = new ColorAnimation() {  
                Duration = TimeSpan.FromSeconds(0.5),  
                EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut }  
            };  
            FocusVisualStyle = null;  
            AddVisualChild(border);  
        }  
        protected void animateBrush(Color color) {  
            anim.To = color;  
            brush.BeginAnimation(SolidColorBrush.ColorProperty, anim);  
        }  
        protected override Size MeasureOverride(Size availableSize) {  
            border.Measure(new Size(Width, Height));  
            border.Arrange(new Rect(border.DesiredSize));  
            return border.DesiredSize;  
        }  
        protected override Size ArrangeOverride(Size finalSize) => new Size(Width, Height);  
        protected override void OnMouseEnter(MouseEventArgs e) => animateBrush(highlightColor);  
        protected override void OnMouseLeave(MouseEventArgs e) => animateBrush(normalColor);  
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) => Command.Invoke();  
        protected override void OnMouseDown(MouseButtonEventArgs e) => animateBrush(downColor);  
        protected override Visual GetVisualChild(int index) => border;  
        protected override int VisualChildrenCount => 1;  
    }  
    

    and put that in Grid/StackPanel, etc. as many times as you want like this:

    <Grid Margin="10">  
        <Grid.Resources>  
            <Style TargetType="local:ActionButton">  
                <Setter Property="Width" Value="24"/>  
                <Setter Property="Height" Value="24"/>  
                <Setter Property="Margin" Value="5 0 5 0"/>  
            </Style>  
        </Grid.Resources>  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="Auto"/>  
            <ColumnDefinition Width="Auto"/>  
            <ColumnDefinition Width="Auto"/>  
            <ColumnDefinition Width="Auto"/>  
            <ColumnDefinition Width="Auto" />  
        </Grid.ColumnDefinitions>  
        <local:ActionButton Icon="m 1396 2749.6 0.7 -513.8 5.1 -13.6 c 8.6 -22.7 19.4 -39.3 36 -55.6 16.4 -16.1 38.1 -28.3 61.7 -35.1 17.3 -4.9 1658.2 -4.9 1676 0 45.6 12.6 80.2 44.6 97.7 90.7 l 5.1 13.6 0.7 513.8 0.5 513.5 h -942 -942 z m 1698.9 179.3 v -28 h -757.3 -757.3 v 28 28 h 757.3 757.3 z m 0 -209.2 v -26.9 h -757.3 -757.3 v 26.9 26.9 h 757.3 757.3 z m 0 -209.2 v -28 h -757.3 -757.3 v 28 28 h 757.3 757.3 z"/>  
        <local:ActionButton Grid.Column="1" Icon="m 1882.9 1934 c -48.4 -7.7 -89.8 -45.8 -105.9 -97.9 -3 -10.3 -3.7 -57 -4.4 -396.7 l -1.2 -385.2 h 605.6 605.6 v 385.2 c 0 320.7 -0.7 386.9 -3.3 395.5 -13.3 43.2 -46.8 77.6 -91.4 93.5 l -14 4.9 -492 0.9 c -270.7 0.5 -495.1 0.2 -499.1 -0.2 z M 2787 1802.6 c 14.7 -5.4 31.6 -20.3 40.2 -35.8 l 7 -12.6 v -259.5 -259.5 l -6.3 -12.2 c -7.5 -14 -20.3 -27.1 -33.4 -34.4 -9.4 -4.9 -10.5 -4.9 -148.4 -4.9 H 2507 l -12.4 7.7 c -14.7 8.9 -21.7 16.4 -30.4 32 l -6.3 11.7 0.2 258.3 0.2 258.3 5.4 11.5 c 7.2 16.1 24.3 32.5 40 38.3 12.2 4.7 16.4 4.9 142.4 4.9 115.2 -0.2 130.9 -0.5 141 -4 z"/>  
        <local:ActionButton Grid.Column="2" Icon="m 1217.8 3596.2 c -77.8 -14.7 -142.1 -69.7 -167.4 -142.8 -11.9 -34.6 -11.2 47.5 -11.9 -1186 -0.9 -1065.9 -0.7 -1145.6 3 -1164.1 14.5 -73.9 70.6 -138.8 140 -162.7 35.8 -12.2 -40 -11.2 982.9 -11.9 858.1 -0.7 947.2 -0.5 963 2.8 17.8 4 35.5 9.4 52.6 16.4 46.3 18.9 44.6 17.3 246.8 220.2 178.6 178.8 184.2 184.7 192.1 201.7 4.7 9.6 10.3 25.5 12.6 35.1 4 16.8 4.2 60.3 4.2 1014.5 v 996.9 l -5.4 19.9 c -10.3 38.8 -29.9 72.5 -59.1 100.7 -26.2 25.5 -55.4 42.5 -92.8 54.2 -15.4 4.7 -20.8 4.9 -286.8 6.5 -149.1 0.7 -650.8 1.6 -1115 1.6 -659.2 0 -847.1 -0.7 -859 -3 z m 2049.5 -218.6 c -0.5 -96.8 0 -121.6 2.3 -121.6 2.3 0 2.8 -99.8 2.3 -506.5 l -0.7 -506.8 -5.1 -13.6 c -17.5 -46 -52.1 -78.1 -97.7 -90.7 -17.8 -4.9 -1644.7 -4.9 -1662 0 -46 13.1 -80.2 44.6 -97.7 90.7 l -5.1 13.6 -0.7 506.8 c -0.5 407.2 0 506.5 2.3 506.1 2.3 -0.5 3.3 24.5 3.7 121.6 l 0.5 122 H 2338.6 3268 Z M 2880.9 1921.3 c 44.6 -15.9 78.1 -50.3 91.4 -93.5 2.6 -8.6 3.3 -73.9 3.3 -388.5 V 1061.1 H 2377 1778.4 l 1.2 378.2 c 0.9 405.8 0.2 383.1 12.2 410.7 5.6 13.1 24.8 38.3 35.8 47.2 19.2 15.4 42.3 26.4 62.4 29.7 4 0.5 225.3 0.7 492 0.2 l 485 -0.9 14 -4.9 z"/>  
        <local:ActionButton Grid.Column="3" Icon="m 2496.7 1808.8 c -15.7 -5.8 -32.7 -22.2 -40 -38.3 l -5.4 -11.5 -0.2 -265.3 -0.2 -265.3 6.3 -11.7 c 8.6 -15.7 15.7 -23.1 30.4 -32 l 12.4 -7.7 h 146.1 c 144.9 0 146.1 0 155.4 4.9 13.1 7.2 25.9 20.3 33.4 34.4 l 6.3 12.2 v 266.5 266.5 l -7 12.6 c -3.7 7 -11.9 16.8 -18 22.2 -20.8 17.8 -16.4 17.3 -170.2 17.5 -133 0 -137 -0.2 -149.4 -4.9 z"/>  
        <local:ActionButton Grid.Column="4" Icon="m 1403 3380.7 c 0.5 -69.2 1.4 -125.5 2.6 -125.1 0.9 0.2 421.9 0.5 935.5 0.5 h 933.8 v 125.1 125.1 h -936.2 -936.2 l 0.5 -125.5004 z"/>  
    </Grid>  
    

    With some of your Path Data, it looks like this:

    94155-capture.png

    To set Color or other properties in xaml, expose those as Full Property if you don't have to bind or as DependencyProperty if you want to bind .

    With this approach, you have full control over your Controls and can extend these Controls to add more functionality, for example, I've another button, CommandButton, which is an ActionButton with custom enabled/disabled style and Keyboard functionality:

    class CommandButton : ActionButton  
    {  
        Color disabledColor;  
        public CommandButton() : base() {  
            Focusable = true;  
            normalColor = Colors.CornflowerBlue;  
            brush.Color = normalColor;  
            disabledColor = Colors.LightGray;  
            IsEnabledChanged += (s,e) => animateBrush(IsEnabled ? normalColor : disabledColor);  
        }  
        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) => animateBrush(highlightColor);  
        protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e) => animateBrush(normalColor);  
        protected override void OnMouseLeave(MouseEventArgs e) { if (IsEnabled) base.OnMouseLeave(e); }  
        protected override void OnKeyUp(KeyEventArgs e) {  
            if (e.Key != Key.Space) return;  
            Command.Invoke();  
        }  
        protected override void OnKeyDown(KeyEventArgs e) {  
            if (e.Key != Key.Space) return;  
            animateBrush(downColor);  
        }  
    }  
    

    and have one more button, MultiCommandButton, which is a CommandButton that executes two tasks sequentially:

    class MultiCommandButton : CommandButton  
    {  
        public Action BeforeCommand { get; set; }  
        public MultiCommandButton() : base() { }  
    
        protected override void OnKeyUp(KeyEventArgs e) {  
            if (e.Key != Key.Space) return;  
            BeforeCommand.Invoke();  
            Command.Invoke();  
        }  
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) {  
            BeforeCommand.Invoke();  
            Command.Invoke();  
        }  
    }  
    
    0 comments No comments

0 additional answers

Sort by: Most helpful