0

I'm trying this code in a markup extension in Silverlight 5.

 public override object ProvideValue(IServiceProvider serviceProvider)
    {
        _target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        _depObj = _target.TargetObject as DependencyObject;
        _depProp = _target.TargetProperty as DependencyProperty;

        return GetText(TextId, DefaultText);
    }

depObj seems to be provided correctly, however depProp seems not to be of type DependencyProperty (The type is Sytem.String (of System.Reflection.PropertyInfo)). The cast results in null.

depProp is representing to the right Text or Content property, but without it being a DependencyProperty I cannot set its value.

Any input greatly appreciated.

SiKo

2 Answers2

0

Not sure why its coming up as a PropertyInfo but you can of course set the value with code something like:

if (TargetProperty is DependencyProperty)
{
    var dependencyObject = target as DependencyObject;
    if (dependencyObject != null)
    {
        var newValue = GetValue();
        dependencyObject.SetValue(TargetProperty as DependencyProperty, newValue);
    }
}
else if (TargetProperty is PropertyInfo)
{
    var pi = target as PropertyInfo;
    pi.SetValue(target, GetValue(), null);
}
Berryl
  • 12,471
  • 22
  • 98
  • 182
  • I don't want to nitpick but c# is type-safe, if you **is** and **as** over and over you are effectively casting over and over. You will be better off to store the **as** result once in a local variable and do a null check which is much faster. The result of an **is** operation is yes or no, while the result of a **as** operation is either null or a successful cast. Neither will throw an exception. – Martin Lottering Apr 30 '13 at 10:04
0

The approach @Berryl gave above could work. But if you also need to get to the DependencyProperty, you can use something like this. This code also demonstrates the subtle differences between silverlight and WPF, but both can work great.

For silverlight or WPF only, you can remove the parts before or after the #else to simplify the code a little bit.

But the part that resolves the dependency property is in the middle (assigning _property).

public override object ProvideValue(IServiceProvider serviceProvider)
{
    IProvideValueTarget Target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

    if (Target == null) {
        throw new InvalidOperationException(
            "Cannot resolve the IProvideValueTarget. Are you binding to a property?");
    }

    /* we need the dependency property (for bindings) */
#if SILVERLIGHT
    PropertyInfo Property = (PropertyInfo)Target.TargetProperty;

    /* resolve the dependency property */
    FieldInfo DepPropertyInfo = Target.TargetObject.GetType()
        .GetField(Property.Name + "Property", BindingFlags.Static | BindingFlags.Public);

    _property = (DependencyProperty)DepPropertyInfo.GetValue(/* obj = */ null);
#else
    _property = Target.TargetProperty as DependencyProperty;
#endif

    if (_property != null) {
#if SILVERLIGHT
        if (Property.Name.StartsWith("Text")) {
            UpdateSourceTrigger = UpdateSourceTrigger.Default;
#else
        if (_property.Name.StartsWith("Text")) {
            UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
#endif
        }
        else {
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        }
    }
Martin Lottering
  • 1,624
  • 19
  • 31