Search code examples
c#wpfxamldependency-propertiesmasking

Dependency Property - Unable to Set Value From XAML


I have the following declaration:

public static readonly DependencyProperty PassColorProperty = DependencyProperty.RegisterAttached("PassColor",
            typeof(string),
            typeof(ColorMasking),
            new PropertyMetadata("#FFCCFF"));

    public string PassColor
    {
        get { return (string)GetValue(PassColorProperty); }
        set { SetValue(PassColorProperty, value); }
    }

At the moment this code does not compile because I haven't added : DependencyProperty to my class. When I add that code it says that the string PassColor is invalid.

Without the string there at all, the code compiles and I can set read the property from within that class. I cannot set it from my XAML though. It says the property doesn't exist. My xaml is:

<TextBox Grid.Column="1" Grid.Row="8" Margin="3" Width="Auto" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
                b:ColorMasking.Mask=" ... Long Regex Command ... "
                b:ColorMasking.PassColor="99FF99" />

The code for setting the Mask works perfectly. I think I have copied all the required stuff too. It is confusing as to why I cannot add another property.

If it matters, this is a variation I've written of this code: How to define TextBox input restrictions?

EDIT:

public class ColorMasking : DependencyObject
{
    private static readonly DependencyPropertyKey _maskExpressionPropertyKey = DependencyProperty.RegisterAttachedReadOnly("MaskExpression",
            typeof(Regex),
            typeof(ColorMasking),
            new FrameworkPropertyMetadata());

    /// <summary>
    /// Identifies the <see cref="Mask"/> dependency property.
    /// </summary>
    /// 
    public static readonly DependencyProperty PassColorProperty = DependencyProperty.Register("PassColor",
            typeof(string),
            typeof(ColorMasking),
            new PropertyMetadata("#99FF99"));

    public static readonly DependencyProperty FailColorProperty = DependencyProperty.Register("FailColor",
            typeof(string),
            typeof(ColorMasking),
            new PropertyMetadata("#FFCCFF"));

    public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask",
            typeof(string),
            typeof(ColorMasking),
            new FrameworkPropertyMetadata(OnMaskChanged));

Solution

  • The code you have posted shows that you are registering an AttachedProperty so the PassColorProperty is not a DependencyPropery of your ColorMasking class. It must be accessed through an object that has that attached property set on it. The attached property will allow you to set that property on other objects and not just

        public static void SetPassColor(DependencyObject obj, string passColor)
        {
            obj.SetValue(PassColorProperty, passColor);
        }
    
        public static string GetPassColor(DependencyObject obj)
        {
            return (string)obj.GetValue(PassColorProperty);
        }
    

    This except from MSDN explains the accessors for an attached property:

    The Get Accessor

    The signature for the GetPropertyName accessor must be:

    public static object Get PropertyName (object target )

    -The target object can be specified as a more specific type in your implementation. For example, the DockPanel.GetDock method types the parameter as UIElement, because the attached property is only intended to be set on UIElement instances.

    -The return value can be specified as a more specific type in your implementation. For example, the GetDock method types it as Dock, because the value can only be set to that enumeration.

    The Set Accessor

    The signature for the SetPropertyName accessor must be:

    public static void Set PropertyName (object target , object value )

    -The target object can be specified as a more specific type in your implementation. For example, the SetDock method types it as UIElement, because the attached property is only intended to be set on UIElement instances.

    -The value object can be specified as a more specific type in your implementation. For example, the SetDock method types it as Dock, because the value can only be set to that enumeration. Remember that the value for this method is the input coming from the XAML loader when it encounters your attached property in an attached property usage in markup. That input is the value specified as a XAML attribute value in markup. Therefore there must be type conversion, value serializer, or markup extension support for the type you use, such that the appropriate type can be created from the attribute value (which is ultimately just a string).