Udostępnij za pośrednictwem


Normal Properties vs. Dependency Properties

In the Silverlight development world there are two kinds of properties that you can have on a Silverlight control: normal C# properties and dependency properties.  The normal C# properties are added to a Silverlight control the same way as they would be added to any C# class:

 public string MyProperty { get; set; }

And then in XAML, you could set the value of the property like this:

 <MyControl MyProperty="someValue" />

This works fine for setting specific values in templates that are unlikely to change or if they do change then the change is always manually made to the XAML file.  But what happens if you want to have the value of the property bound to some other value that is retrieved from a database, web service, etc?  You might try Binding to the property like so:

 <MyControl MyProperty="{Binding DynamicPropertyValue}" />

Where DynamicPropertyValue was a property on the parent element that you wanted to to have your property get data from.  But when you run it, you get and error similar to the following:

Silverlight error
ErrorCode: 2260
ErrorType: ParserError
Message: AG_E_PARSER_BAD_PROPERTY_VALUE
XAMLFile:
Line: 1
Position: 6030

Enter the DependencyProperty.  The DependencyProperty is a property that can be bound dynamically.  The downside is that there is a bit more overhead.  Here is the same property from above expressed as a DependencyProperty:

 /// <summary>
/// Gets or sets the MyProperty value.
/// </summary>
public string MyProperty
{
    get { return (string)GetValue(MyProperty); }
    set { SetValue(MyProperty, value); }
}

/// <summary>
/// Dependency field of MyProperty property.
/// </summary>
public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", 
                                    typeof(string), 
                                    typeof(MyControl),
                                    null);

Now if you want to add some logic that happens when the property value is changed you can set up your DependencyProperty like this:

 /// <summary>
/// Dependency field of MyProperty property.
/// </summary>
public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", 
                 typeof(string), 
                 typeof(MyControl),
                 new PropertyMetadata(
 new PropertyChangedCallback(OnMyPropertyPropertyChanged)));

private static void OnMyPropertyPropertyChanged(DependencyObject sender, 
            DependencyPropertyChangedEventArgs args)
{
    MyControl myControl = (MyControl)sender;
    myControl.OnMyPropertyChanged((string)args.NewValue);
}

/// <summary>
/// Event handler for the MyProperty property changed event.
/// </summary>
/// <param name="newMyPropertyValue">The new MyProperty value to set.</param>
protected virtual void OnCurrentRatingValueChanged(string newMyPropertyValue)
{
    if (newMyPropertyValue.Length == 0)
    {
        throw new ArgumentException("MyProperty cannot be null.");
    }
}

Anyway, there you have it, you can now bind data to properties in XAML.  As usual, should you find this information to have been helpful, or less than helpful, please feel free to leave comments.