I have a markup extension that is working with Binding. Things work well except when the markup extension is used in a DataTemplate which is then used by a ContentControl that is bound to the same property as a ListView with IsSynchronizedWithCurrentItem=true. How can I get the CurrentItem from my templated controls instead of each controls' datacontext (which is the collection, not the item)
e.g.
<ListView ItemsSource="{Binding Things}" IsSynchronizedWithCurrentItem="True" />
and
<ContentControl
ContentTemplate="{StaticResource thingsTemplate}"
Content="{Binding Things}" />
and a "thingsTemplate" with anything you would expect.
My MarkupExtension's ProvideValue looks like this:
public override object ProvideValue(IServiceProvider serviceProvider)
{
//delegate binding creation etc. to the base class
object val = base.ProvideValue(serviceProvider);
//try to get bound items for our custom work
DependencyObject targetObject;
DependencyProperty targetProperty;
bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);
if (status && targetObject is FrameworkElement)
{
FrameworkElement element = targetObject as FrameworkElement;
BindingExpression elementGetBindingExpression = val as BindingExpression;
INotifyPropertyChanged dataContext = element.DataContext as INotifyPropertyChanged;
element.DataContextChanged += (changedElement, dcc) =>
{
FrameworkElement fe = changedElement as FrameworkElement;
var ebe = fe.GetBindingExpression(targetProperty);
var dc = fe.DataContext as INotifyPropertyChanged;
if (null != ebe && null != dc)
wirePropertyChanged(ebe, dc);
};
// This is where things go terribly bad and I cannot figure out how to handle things.
// it works fine for a datatemplate that is bound directly, but not with IsSynchronized...
FrameworkElement templatedParentElement = element.TemplatedParent as FrameworkElement;
if (templatedParentElement is ContentPresenter && (templatedParentElement as ContentPresenter).Content is INotifyPropertyChanged)
dataContext =
(templatedParentElement as ContentPresenter).Content as INotifyPropertyChanged;
else
dataContext = templatedParentElement.DataContext as INotifyPropertyChanged;
if (null != templatedParentElement)
wirePropertyChanged(elementGetBindingExpression, dataContext);
if (null != elementGetBindingExpression && null != dataContext)
wirePropertyChanged(elementGetBindingExpression, dataContext);
return val;
}
else return this;
}
Any pointers to how WPF and ContentControl do their magic of IsSynchronizedWithCurrentItem would help. I know I could change the "Things" property to which things are bound to an ICollectionView (it is an ObservableCollection) and read CurrentItem off of that, but I am hoping for a more general solution that will work in all cases of the ContentControl and DataTemplate.