Just to add to that, inside your PropertyChangedCallback, a typical pattern is going to be revert on incorrect/out-of-range values, before throwing an exception.
If you don't do the revert, the out-of-range value will actually still be set, and your state will be invalid.
You'll see examples of this "poor man's coercian" in some of the Silverlight Toolkit. Here's the AutoCompleteBox.cs source.
The pattern is something like:
int newValue = (int)e.NewValue;
if (newValue < 0)
{
source._ignorePropertyChange = true;
d.SetValue(e.Property, e.OldValue);
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Properties.Resources.AutoComplete_OnMinimumPopulateDelayPropertyChanged_InvalidValue, newValue), "value");
}
You can also implement your own "read-only" Silverlight dependency properties in a similar manner, though it'll require a private field to indicate whether you're setting or reverting the value.