问题
I have an adorner defined as follows:
private class ErrorAdorner : Adorner
{
private readonly Border _errorBorder;
public ErrorAdorner(UIElement adornedElement)
: base(adornedElement)
{
_errorBorder = new Border();
_errorBorder.BorderThickness = new Thickness(2);
_errorBorder.BorderBrush = Brushes.Red;
Image img = new Image();
img.HorizontalAlignment = HorizontalAlignment.Right;
img.VerticalAlignment = VerticalAlignment.Center;
img.Stretch = Stretch.None;
Binding imgBinding = new Binding
{
Source = adornedElement,
Path = new PropertyPath(IconProperty)
};
img.SetBinding(Image.SourceProperty, imgBinding);
Binding ttBinding = new Binding
{
Source = adornedElement,
Path = new PropertyPath(ErrorMessageProperty)
};
img.SetBinding(ToolTipProperty, ttBinding);
_errorBorder.Child = img;
}
protected override Size MeasureOverride(Size constraint)
{
AdornedElement.Measure(constraint);
return AdornedElement.RenderSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
_errorBorder.Arrange(new Rect(finalSize));
return finalSize;
}
protected override Visual GetVisualChild(int index)
{
if (index == 0)
return _errorBorder;
throw new ArgumentOutOfRangeException("index");
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
}
ErrorMessage
and Icon
are attached properties declared in an enclosing class (ErrorProvider
). The adorner is added to an element when the ErrorMessage
property is set to a non-null value.
My problem is that while the adorner is properly rendered, the ToolTip
on the image doesn't show up when I move the mouse over it. I know it isn't a binding issue: when I examine the controls with Snoop, I can see that the ToolTip
property has the expected value. I suspect the problem is related to hit testing, because I can't receive any mouse related event in the adorner... The IsHitTestVisible
property is set to true, so I don't understand why I don't receive the events.
Any idea?
回答1:
Ok, this is something that has bitten me before also. When you define your own visual tree, it isn't enough to just return the visual children, you also need to tell WPF that you've added them. At the end of your constructor just add this:
this.AddVisualChild(_errorBorder);
this.AddLogicalChild(_errorBorder);
You should also implement the LogicalChildren
property:
protected override System.Collections.IEnumerator LogicalChildren
{
get
{
yield return _errorBorder;
}
}
If you had multiple children, I'd use the UIElementCollection
. It will add them to the visual and logical trees, and you can just use it from the LogicalChildren
, VisualChildrenCount
, and GetVisualChild
overrides.
来源:https://stackoverflow.com/questions/6941538/tooltip-on-adorner-doesnt-show-up