Ricardo Peres
Ricardo Peres

Reputation: 14555

Evaluate Binding Path Dynamically in Silverlight in XAML

How can I evaluate a binding path dynamically, that is, the actual path comes from a property? For example, suppose I have a property of DisplayMemberPath, and I wanted to have something like:

Content="{Binding Path=(DisplayMemberPath)}"

I know that this doesn't work, it's just to explain what I wanted. I know how to build a custom DataTemplate by code and set it dynamically, but that's not what I want.

Upvotes: 0

Views: 113

Answers (1)

Martin
Martin

Reputation: 6162

You can use a custom behavior:

<SomeControl>
    <Interaction.Behaviors>
        <DynamicBindingBehavior TargetProperty="Content"
            BindingPath="{Binding DisplayMemberPath}"/>
    </Interaction.Behaviors>
    ...
</SomeControl>

and the code:

public class DynamicBindingBehavior : Behavior<DependencyObject>
{
    private string m_targetProperty;
    public string TargetProperty
    {
        get { return m_targetProperty; }
        set
        {
            m_targetProperty = value;
            TryFindTargetProperty();
        }
    }

    private DependencyProperty m_targetDependencyProperty;

    private void TryFindTargetProperty()
    {
        if (m_targetProperty == null || AssociatedObject == null)
        {
            m_targetDependencyProperty = null;
        }
        else
        {
            var targetDependencyPropertyInfo = AssociatedObject.GetType()
                .GetProperty( TargetProperty + "Property", typeof( DependencyProperty ) );
            m_targetDependencyProperty =
                (DependencyProperty) targetDependencyPropertyInfo.GetValue(
                AssociatedObject, null );
        }
    }

    public string BindingPath
    {
        get { return (string) GetValue( BindingPathProperty ); }
        set { SetValue( BindingPathProperty, value ); }
    }

    public static readonly DependencyProperty BindingPathProperty =
        DependencyProperty.Register( "BindingPath", typeof( string ),
        typeof( DynamicBindingBehavior ),
        new PropertyMetadata( BindingPathChanged ) );

    private static void BindingPathChanged(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        ((DynamicBindingBehavior) d).BindingPathChanged();
    }

    private void BindingPathChanged()
    {
        if (m_targetDependencyProperty == null) return;

        if (BindingPath == null)
        {
            AssociatedObject.ClearValue(m_targetDependencyProperty);
        }
        else
        {
            BindingOperations.SetBinding( AssociatedObject,
                m_targetDependencyProperty, new Binding( BindingPath ) );
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        TryFindTargetProperty();
    }

    protected override void OnDetaching()
    {
        if (m_targetDependencyProperty != null)
            AssociatedObject.ClearValue( m_targetDependencyProperty );

        base.OnDetaching();
        m_targetDependencyProperty = null;
    }
}

Upvotes: 2

Related Questions