§ August 26, 2009 06:43 by
beefarino |
I'm really digging that I get to work with WPF at the moment. Using advanced databinding features against MVVM are making quick work of the menial "datapult" applications I'm pounding out. I still have a lot to absorb, but I'm getting there.
Being a n00b to XAML and WPF, I often find myself lost in a fog when things don't work. E.g., this afternoon I spent a good 30 minutes trying to decipher a binding problem. I was trying to use the data context of a TreeViewItem in the text of it's header template (you can laugh at my XAML, this is just me hacking):
<TreeViewItem ItemsSource="{Binding Profiles}">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Count}"/>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>
I tried several binding paths in the TextBlock, but nothing would show up in the tree node. I ended up switching gears and trying to figure out what data context was actually available to the header data template. Finding nothing from a cursory googling, I ended up creating a value converter that would convert the data object into it's underlying type:
namespace My.Converters
{
public class ObjectToTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if( null == value )
{
return "null";
}
return value.GetType();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
The Convert implementation will return the System.Type of the data context (line 12), or the string "null" if no context is available (line 9). At this point I can alter the XAML to simply spit out the actual type of the data context, giving me a clue as to why I'm clueless:
<Window ...
xmlns:Converters="clr-namespace:My.Converters">
...
<Window.Resources>
<Converters:ObjectToTypeConverter x:Key="ObjectToTypeConverter" />
</Window.Resources>
<TreeViewItem ItemsSource="{Binding Profiles}">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ObjectToTypeConverter}}"/>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>
...
Anyway, long story short, in my particular case the data context for the TreeViewItem header template is actually null - which makes no sense to me, I would have assumed it would have been the TreeViewItem's data context. A quick relative sourcing of the binding solved my issue:
<TreeViewItem ItemsSource="{Binding Profiles}">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Profiles.Count}"
DataContext="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}}"/>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>