Итак, ваша проблема в том, что у вас есть пользовательский элемент управления внутри Canvas. Ваш UserControl должен знать, когда Canvas получает IsHitTestVisible со значением false.
IsHitTestVisible не является свойством, которое наследуется по дереву. Если вы установите IsHitTestVisible = false для объекта, это свойство не изменится на его дочерних объектах.
Таким образом, один из подходов состоит в том, что вы можете создать свойство в вашем UserControl, скажем «IsParentHitTestVisible», и связать это свойство в вашем UserControl со свойством Canvas IsHitTestVisible. Затем в вашем UserControl вы можете обрабатывать уведомления об изменениях для свойства.
Вот решение, которое я попробовал.
Сначала я создал вспомогательный класс, чтобы упростить получение уведомлений об изменениях для свойства:
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);
}
}
Это позволяет вам отслеживать свойство объекта и получать событие при его изменении. Таким образом, вы можете сделать что-то вроде:
PropertyNotifier pn = new PropertyNotifier();
pn.Monitor("IsHitTestVisible", theCanvas);
pn.PropertyChanged += new EventHandler(pn_PropertyChanged);
и событие PropertyChanged будет запущено, если IsHitTestVisible изменится на "theCanvas".
Итак, я настроил событие Loaded в UserControl так:
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;
}
}
}
Я не знаю, сработает ли это в каждой ситуации, поэтому вам нужно проверить это. Там также может быть более простой способ, но это лучшее, что я мог придумать.