t4nky
t4nky

Reputation: 437

Attached property not accepting default value for double

I'm trying to use an attached property to set the left margin of a grid exclusively. Sadly, it doesn't work. The property throws a XamlParseException "Default value type does not match type of property".

My attached property

public class Margin : DependencyObject
{
    #region Dependency Properties
    public static readonly DependencyProperty LeftProperty =
        DependencyProperty.RegisterAttached("Left", typeof(double), typeof(Margin),
        new PropertyMetadata(new UIPropertyMetadata(0d, OnMarginLeftChanged)));
    #endregion

    #region Public Methods
    public static double GetLeft(DependencyObject obj)
    {
        return (double)obj.GetValue(LeftProperty);
    }
    public static void SetLeft(DependencyObject obj, double value)
    {
        obj.SetValue(LeftProperty, value);
    }
    #endregion

    #region Private Methods
    private static void OnMarginLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var element = obj as FrameworkElement;
        var margin = element.Margin;
        margin.Left = (double)e.NewValue;
        element.Margin = margin;
    }
    #endregion
}

My user Interface

<Window x:Class="MSPS.View.Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ctrl="clr-namespace:MSPS.View.Controls;assembly=MSPS.View.Controls"
        xmlns:ap="clr-namespace:MSPS.View.Controls.AttachedProperties;assembly=MSPS.View.Controls"
        Title="MainWindow" Height="350" Width="525">
    <Grid Background="Blue" ap:Margin.Left="20">

    </Grid>
</Window>

Upvotes: 1

Views: 1426

Answers (4)

Pitka
Pitka

Reputation: 525

DependencyProperty.RegisterAttached("Left", typeof(double), typeof(Margin), new PropertyMetadata(0.0, OnMarginLeftChanged));

Upvotes: 0

Anatoliy Nikolaev
Anatoliy Nikolaev

Reputation: 22702

You not correctly set PropertyMetadata, in this case you two times create the instance of this class:

DependencyProperty.RegisterAttached("Left", typeof(double), typeof(Margin),
    new PropertyMetadata(new UIPropertyMetadata(0d, OnMarginLeftChanged)));

Should be so:

DependencyProperty.RegisterAttached("Left", typeof(double), typeof(Margin),
    new UIPropertyMetadata(0.0, OnMarginLeftChanged));

Or like this:

DependencyProperty.RegisterAttached("Left", typeof(double), typeof(Margin),
    new PropertyMetadata(0d, OnMarginLeftChanged));

Upvotes: 3

user3455395
user3455395

Reputation: 161

Your attached property change handler gets called for the default value too unless I'm mistaken. Try using nullable double. I'm not sure if UIPropertyMetadata will do you any good - it has some UI specific properties, which might be an overhead in your case. Try using just default constructor without giving a specific Metadata object type.

Upvotes: 0

Tony Vitabile
Tony Vitabile

Reputation: 8614

I suspect that your problem may be in here:

private static void OnMarginLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var element = obj as FrameworkElement;
    var margin = element.Margin;
    margin.Left = (double)e.NewValue;
    element.Margin = margin;
}

Every FrameworkElement has a Margin property that has the Framework Thickness type. This is a struct with 4 double properties, Left, Top, Right and Bottom.

Instead, write it like this:

private static void OnMarginLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var element = obj as FrameworkElement;
    var margin = element.Margin;
    SetLeft( margin, (double)e.NewValue );
    element.Margin = margin;
}

That will set your attached property.

That said, why are you using an attached property for Margins when the framework already provides a property that your existing code would work with?

Upvotes: 0

Related Questions