Question

I have a need to set Content property of a ContentPresenter to a DynamicResource, which key is known at runtime. DynamicResource's Key is not a dependency property, so I cannot insert a binding there, and that's why I've created an attached property, which serves as a proxy for the Content:

public static class ContentPresenterHelper {

    private static void ContentResourceKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {

        var element = d as ContentPresenter;
        if (element != null) {

            element.SetResourceReference(ContentPresenter.ContentProperty, e.NewValue);
        }
    }

    public static readonly DependencyProperty ContentResourceKeyProperty = DependencyProperty.RegisterAttached("ContentResourceKey",
        typeof(object),
        typeof(ContentPresenterHelper),
        new PropertyMetadata(String.Empty, ContentResourceKeyChanged));

    public static void SetContentResourceKey(ContentPresenter element, object value) {

        element.SetValue(ContentResourceKeyProperty, value);
    }

    public static object GetContentResourceKey(ContentPresenter element) {

        return element.GetValue(ContentResourceKeyProperty);
    }
}

I'm using it in the following way:

<ContentPresenter u:ContentPresenterHelper.ContentResourceKey="{Binding SomeProp}" />

I've used similar approach when assigning dynamically image from resources to an Image's Source property and that worked.

However, in this particular case attempt to solve the problem in the way I've shown results in an infinite recursion:

PresentationFramework.dll!System.Windows.FrameworkElement.IsLoaded.get()    Unknown
PresentationFramework.dll!MS.Internal.FrameworkObject.IsLoaded.get()    Unknown
PresentationFramework.dll!System.Windows.BroadcastEventHelper.IsParentLoaded(System.Windows.DependencyObject d) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.IsLoaded.get()    Unknown
PresentationFramework.dll!MS.Internal.FrameworkObject.IsLoaded.get()    Unknown
PresentationFramework.dll!System.Windows.BroadcastEventHelper.IsParentLoaded(System.Windows.DependencyObject d) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.IsLoaded.get()    Unknown
PresentationFramework.dll!MS.Internal.FrameworkObject.IsLoaded.get()    Unknown
...

Why is it so? How can I solve this problem?

Was it helpful?

Solution

When messing around with ContentPresenter, always remember that ContentPresenter.Content is a very special property: it affects the DataContext. In combination with data binding this can produce all sorts of weird effects. Generally speaking, binding ContentPresenter.Content through DataContext is not reliable and should be avoided. Try using ContentControl, as it does not connect its DataContext to Content in this manner. Also, instead of an attached property, I'd write a converter to look up your dynamic resource by key, and use it to bind Content directly, but it's a matter of taste.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top