So your problem is that you have a UserControl inside of a Canvas. Your UserControl needs to know when the Canvas gets IsHitTestVisible set to false.
IsHitTestVisible is not a property that gets "inherrited" down the tree. If you set IsHitTestVisible=false on an object, that property doesn't change on it children.
So, one approach is that you can create a property on your UserControl, say "IsParentHitTestVisible" and bind that property on your UserControl to the Canvas's IsHitTestVisible property. Then in your UserControl, you can handle the change notifications for the property.
Here is the solution that I tried.
First, I created a helper class to make it easier to get the change notifications for a property:
public class PropertyNotifier : UserControl
{
public static readonly DependencyProperty ThePropertyProperty =
DependencyProperty.Register("TheProperty", typeof(object), typeof(PropertyNotifier), new PropertyMetadata(OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PropertyNotifier obj = (PropertyNotifier)d;
if (obj.PropertyChanged != null)
{
obj.PropertyChanged(obj, null);
}
}
public event EventHandler PropertyChanged;
public void Monitor(string prop, Object instance)
{
Binding binding = new Binding();
binding.Source = instance;
binding.Path = new PropertyPath(prop);
SetBinding(ThePropertyProperty, binding);
}
public void StopMonitoring()
{
SetValue(ThePropertyProperty, null);
}
}
This just lets you monitor a property on an object and get an event when it changes. So you can do something like:
PropertyNotifier pn = new PropertyNotifier();
pn.Monitor("IsHitTestVisible", theCanvas);
pn.PropertyChanged += new EventHandler(pn_PropertyChanged);
and the PropertyChanged event will be fired if IsHitTestVisible changes on "theCanvas".
So, I set up the Loaded event in the UserControl to look like:
private List<PropertyNotifier> notifiers = new List<PropertyNotifier>();
void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
foreach (var notifier in notifiers)
{
notifier.PropertyChanged -= pn_PropertyChanged;
notifier.StopMonitoring();
}
notifiers.Clear();
foreach (var parent in GetAllParents(this))
{
PropertyNotifier pn = new PropertyNotifier();
pn.Monitor("IsHitTestVisible", parent);
pn.PropertyChanged += new EventHandler(pn_PropertyChanged);
notifiers.Add(pn);
}
}
static IEnumerable<FrameworkElement> GetAllParents(FrameworkElement element)
{
FrameworkElement parent = element.Parent as FrameworkElement;
if (parent != null)
{
yield return parent;
foreach(var el in GetAllParents(parent))
{
yield return el;
}
}
}
I don't know if this will work in every situation, so you will need to test it out. There also might be an easier way, but this is the best that I could come up with.