DependencyProperties on UIElement
s do not support databinding (you get something like:
"Cannot find governing FrameworkElement..")
. If you try, you get an error because WPF can not resolve the DataContext. From what I know, you get binding support if you inherit FrameworkElement or Freezable, but In this case I can not simply change the base class. Is there any way to get the UIElement to support data binding?
I've tried to add the DataContext property to the UIElement class like this:
FrameworkElement.DataContextProperty.AddOwner(typeof(Bitmap), new
FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
I also tried to bind by specifying "ElementName" in the binding expression, but I am still unable to resolve the parent DataContext (I thought that binding explicitly by ElementName would simply remove the need to resolve the DataContext).
This is the binding. The class in question is called "Bitmap".
<Utils:Bitmap Source="{Binding Path=Icon}" />
<TextBlock Grid.Row="1" Grid.ColumnSpan="3" MaxWidth="90" Text="{Binding Path=Name}" TextWrapping="Wrap" TextAlignment="Center"/>
The textblock binding works as expected, the first binding does not. The bound viewmodel has both properties (I bound to the Image class before and it worked).
The bitmap class can be found at this blog: http://blogs.msdn.com/b/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx
With some extended binding diagnostics, I get this output:
System.Windows.Data Warning: 65 : BindingExpression (hash=14926099): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=117163); target property is 'Source' (type 'BitmapSource')
System.Windows.Data Warning: 63 : BindingExpression (hash=6195855): Resolving source (last chance)
System.Windows.Data Warning: 65 : BindingExpression (hash=6195855): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=55762700); target property is 'Source' (type 'BitmapSource')
System.Windows.Data Warning: 63 : BindingExpression (hash=48657561): Resolving source (last chance)
System.Windows.Data Warning: 65 : BindingExpression (hash=48657561): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Icon; DataItem=null; target element is 'Bitmap' (HashCode=35264868); target property is 'Source' (type 'BitmapSource')
As noted you can bind on any object which inherits from
DependencyObject
, if you want aDataContext
, I'd suggest you just make the class inherit fromFrameworkElement
. Even shapes like Rectangle do so, if you have some image-control it only makes sense to choose a higher level as the base-class.You can use
{Binding Source={x:Reference elementName}}
instead of{Binding ElementName=elementName}
.You have to inherit
FrameworkElement
to use data binding. If you cannot change the base class, the only option you have is, as H.B. said, create an adapter that will be derived fromFrameworkElement
and will delegate all the functionality to an instance of the existing class derived fromUIElement
.See http://msdn.microsoft.com/en-us/library/ms743618.aspx for more information on what the base framework classes (like
UIElement
andFrameworkElement
) provide.Update:
Even though MSDN (link above) says that the data binding support is introduced on the
FrameworkElement
level, it IS possible to set binding on anyDependencyObject
. The only thing is that in this case you cannot useDataContext
as an implicit source for the binding and you cannot useElementName
for referring to the source.What you can do is to set binding programmatically and specify source explicitly:
OR you can use a little trick and use
RelativeSource
for referring to an element in the visual tree (in this case any parentFrameworkElement
):