How to remove Top and Left Margin/Padding from Geometry/FrameworkElement?

Emon Haque 3,176 Reputation points
2021-06-27T15:57:35.44+00:00

Here's two Geometry:

109702-test.gif

The left one is a Path inside a Border and the right one is Geometry drawn OnRender with a ScaleTransform. The right one always adds a Margin/Padding on Top and Left and as a result the + symbol on the bottom-right always gets out of the rectangular bound! How to remove those Margin/Padding?

Here's the code for the right one:

class ButtonWithoutBorder : FrameworkElement  
{  
    Geometry geometry;  
    ScaleTransform transform;  
    SolidColorBrush brush;  
    ColorAnimation animation;  
    Color normal, highlight, pressed;  
    double scaleFactor, cx, cy;  
    public string Icon { get; set; }  
    public double Size { get; set; }  
    public ButtonWithoutBorder() {  
        normal = Colors.Black;  
        highlight = Colors.CornflowerBlue;  
        pressed = Colors.Coral;  
        brush = new SolidColorBrush(normal);  
        animation = new ColorAnimation() {  
            Duration = TimeSpan.FromMilliseconds(250),  
            EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut }  
        };  
        //Margin = new Thickness(0);  
    }  
    void animate(Color color) {  
        animation.To = color;  
        brush.BeginAnimation(SolidColorBrush.ColorProperty, animation);  
    }  
    protected override void OnInitialized(EventArgs e) {  
        if (Size == 0) Size = 250;  
        Width = Size;  
        Height = Size;  
        geometry = Geometry.Parse(Icon);  
        scaleFactor = Height / geometry.Bounds.Height;  
        cx = geometry.Bounds.TopLeft.X;  
        cy = geometry.Bounds.TopLeft.Y;  
        transform = new ScaleTransform(scaleFactor, scaleFactor) { CenterX = cx, CenterY = cy };  
    }  
    protected override void OnRender(DrawingContext dc) {  
        dc.DrawRectangle(null, new Pen(Brushes.Red, 1), new Rect(0, 0, Width, Height));  
        dc.PushTransform(transform);  
        dc.DrawGeometry(brush, null, geometry);  
    }  
    protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) => new PointHitTestResult(this, hitTestParameters.HitPoint);  
    protected override void OnMouseEnter(MouseEventArgs e) => animate(highlight);  
    protected override void OnMouseLeave(MouseEventArgs e) => animate(normal);  
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) => animate(pressed);  
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) => animate(highlight);          
}  

and here's the left one:

class ButtonWithBorder : Border  
{  
    SolidColorBrush brush;  
    ColorAnimation animation;  
    Color normal, highlight, press;  
    public string Icon { get; set; }  
    public double Size { get; set; }  
    public ButtonWithBorder() {  
        normal = Colors.Black;  
        highlight = Colors.CornflowerBlue;  
        press = Colors.Coral;  
        brush = new SolidColorBrush(normal);  
        animation = new ColorAnimation() {  
            Duration = TimeSpan.FromMilliseconds(250),  
            EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut }  
        };  
        BorderBrush = Brushes.Red;  
        BorderThickness = new Thickness(1);  
        Background = Brushes.Transparent;  
        Child = new Path() {  
            Fill = brush,  
            Stretch = Stretch.Uniform  
        };  
        Loaded += onLoaded;  
    }  
    void onLoaded(object sender, RoutedEventArgs e) {  
        if (Size == 0) Size = 250;  
        Width = Size;  
        Height = Size;  
        ((Path)Child).Data = Geometry.Parse(Icon);  
    }  
    void animate(Color color) {  
        animation.To = color;  
        brush.BeginAnimation(SolidColorBrush.ColorProperty, animation);  
    }  
    protected override void OnMouseEnter(MouseEventArgs e) => animate(highlight);  
    protected override void OnMouseLeave(MouseEventArgs e) => animate(normal);  
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) => animate(press);  
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) => animate(highlight);  
}  

You can use it in MainWindow.xaml like this:

<Grid>  
    <Grid.Resources>  
        <System:String x:Key="icon">M18,14H20V17H23V19H20V22H18V19H15V17H18V14M12,3C16.42,3 20,4.79 20,7C20,9.21 16.42,11 12,11C7.58,11 4,9.21 4,7C4,4.79 7.58,3 12,3M4,9C4,11.21 7.58,13 12,13C16.42,13 20,11.21 20,9V9L20,12.08L19,12C16.41,12 14.2,13.64 13.36,15.94L12,16C7.58,16 4,14.21 4,12V9M4,14C4,16.21 7.58,18 12,18H13C13,19.05 13.27,20.04 13.75,20.9L12,21C7.58,21 4,19.21 4,17V14Z</System:String>  
    </Grid.Resources>  
    <Grid.ColumnDefinitions>  
        <ColumnDefinition/>  
        <ColumnDefinition/>  
    </Grid.ColumnDefinitions>  
    <local:ButtonWithBorder Icon="{StaticResource icon}"/>  
    <local:ButtonWithoutBorder Grid.Column="1" Icon="{StaticResource icon}"/>  
</Grid>  
Developer technologies | Windows Presentation Foundation
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. DaisyTian-1203 11,646 Reputation points
    2021-06-29T07:17:25.6+00:00

    Please update your line 32 and line 33 in ButtonWithoutBorder.cs as below:

    cx = (geometry.Bounds.TopLeft.X)*1.1;  
    cy = (geometry.Bounds.TopLeft.Y)*1.1;  
    

    It will run like:
    110030-capture.png


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.