after some time of silverlight-development I am currently doing some WPF work...
I often used this trick to make my life easier in some of my ValueConverters:
public class MyCovnerterWithDataContext : FrameworkElement, IValueConverter
{
private MyDataContextType Data
{
get { return this.DataContext as MyDataContextType; }
}
....
Now I could access my DataContext in the Converter-Method, which comes handy in lots of situations as you can imagine.
I tried the same trick in WPF and found out, that unfortunately this does not work at all. There is the following error in the debug-output:
"Cannot find element that provides DataContext"
I suppose the resources aren't part of the visual tree in WPF whereas they are in Silverlight.
So - is my little trick possible in WPF as well? Is my little trick to be considered a dirty hack?
What's your opinion and suggestions?
Regards Johannes
Update: as requested some more info - actually a minimal example:
XAML:
<Window x:Class="WpfDataContextInResources.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfDataContextInResources"
x:Name="window"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:TestWrapper x:Key="TestObj" />
</Window.Resources>
<StackPanel>
<TextBlock Text="{Binding Text}" />
<TextBlock Text="{Binding DataContext.Text, Source={StaticResource TestObj}, FallbackValue='FALLBACK'}" />
</StackPanel>
</Window>
the .cs file:
namespace WpfDataContextInResources
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new DataClass()
{
Text = "Hello",
};
}
}
public class TestWrapper : FrameworkElement {}
public class DataClass
{
public string Text { get; set; }
}
}
At least on my PC the lower text-block stays on the fallbackvalue
Update #2:
I tried the suggestion Matrin posted (deriving from DependencyObject, creating own DependencyProperty, etc) - it did not work either. This time however the error-message is a different one:
"System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'TestWrapper' (HashCode=28415924); target property is 'TheData' (type 'Object')"
I also have some suggestions for workarounds though:
1.) - Use MultiBinding --> not compatible with Silverlight, not enough in some cases.
2.) - Use yet another wrapping object, set DataContext by hand in code-behind, like this --> fully compatible with Silverlight (apart from the fact, that you can't use a Framework-Element directly - you have to make an empty class deriving from it)
xaml:
<Window.Resources>
<FrameworkElement x:Key="DataContextWrapper" />
<local:TestWrapper x:Key="TestObj" DataContext="{Binding DataContext, Source={StaticResource DataContextWrapper}}" />
...
code behind:
//of course register this handler!
void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var dcw = this.Resources["DataContextWrapper"] as FrameworkElement;
dcw.DataContext = this.DataContext;
}