WPF装饰器出现在鼠标悬停动画上-什么';什么样的款式最好?
装饰符是在图像的部分上定义的。所需的行为如下所示:WPF装饰器出现在鼠标悬停动画上-什么';什么样的款式最好?,wpf,adorner,Wpf,Adorner,装饰符是在图像的部分上定义的。所需的行为如下所示: 当鼠标位于图像区域(包括装饰器区域)上时,装饰器将出现 当鼠标离开图像和装饰器区域时,装饰器消失 装饰物的出现和消失将相应地通过淡入/淡出动画进行 单击装饰器区域必须引发事件AdornerClicked 单击图像上未被装饰条隐藏的区域,必须将ImageClicked唤醒 一个幼稚的实现 在图像的MouseEnter和MouseLeave事件的装饰器不透明度上附加动画,并为每个事件附加单击事件。但是,当鼠标直接位于装饰条上方时,这会导致装饰条消失
满足要求的正确模式是什么?一个有点老的问题,但我刚刚遇到了同样的问题,找不到答案,所以这里是我想到的 因此,问题是控件及其装饰器重叠,将装饰器设置为可见会触发装饰控件上的鼠标删除,因为它现在已被装饰器覆盖 解决方案是对修饰控件及其修饰器上的每个MouseEnter和MouseLeave进行反应,并手动执行命中测试。如果其中任何一个被击中,则装饰条应可见,否则会折叠 因此,您需要能够从装饰控件获取装饰器,反之亦然。从装饰器获取装饰控件没有问题(使用AdorneElement属性),但是框架(AFAIK)不提供为控件获取装饰器,因此我使用字典将控件映射到它们的装饰器列表 以下是我的Panel派生类(包含并排列我的控件及其装饰器)中的代码:
private readonly Dictionary\u controlToAdornersMap;
...
私有void CreateMyControl()
{
var control=new MyControl();
control.MouseEnter+=onmycontrolmouseenterLeave;
control.MouseLeave+=onmycontrolmouseenterrorve;
添加(对照组);
地址装饰器(控制);
}
专用void addarendors(控件)
{
var myAdorner=新的myAdorner(控件);
myAdorner.MouseEnter+=OnMyAdornerMouseEnterOrLeave;
myAdorner.MouseLeave+=OnMyAdornerMouseEnterOrLeave;
var adornerLayer=adornerLayer.GetAdornerLayer(控件);
添加(myAdorner);
_controlToAdornersMap[control]=新列表{myAdorner};
}
MyControl MouseenterOrleave上的私有void(对象发送方,MouseEventArgs e)
{
HitTestAndSetAdornerVisibility((MyControl)发送方,e);
}
MyadornerMouseenterOrLeave上的私有void(对象发送方,MouseEventArgs e)
{
var adorner=(adorner)发送方;
HitTestAndSetAdornerVisibility((MyControl)adorner.AdornedElement,e);
}
私有void HitTestAndSetAdornerVisibility(MyControl控件,MouseEventArgs e)
{
变量装饰器=_controlToAdornersMap[control];
var hitTestSubjects=新列表{control}.Concat(装饰器);
var hit=hitTestSubjects.Any(i=>visualtreeheloper.HitTest(i,e.GetPosition(i))!=null);
SetAdornerVisibility(装饰器,点击?可见性。可见:可见性。折叠);
}
私有静态void SetAdornerVisibility(IEnumerable adorners,可见性)
{
if(装饰条!=null)
foreach(装饰器中的var装饰器)
可见性=可见性;
}
private readonly Dictionary<Control, List<Adorner>> _controlToAdornersMap;
...
private void CreateMyControl()
{
var control = new MyControl();
control.MouseEnter += OnMyControlMouseEnterOrLeave;
control.MouseLeave += OnMyControlMouseEnterOrLeave;
Children.Add(control);
AddAdorners(control);
}
private void AddAdorners(Control control)
{
var myAdorner = new MyAdorner(control);
myAdorner.MouseEnter += OnMyAdornerMouseEnterOrLeave;
myAdorner.MouseLeave += OnMyAdornerMouseEnterOrLeave;
var adornerLayer = AdornerLayer.GetAdornerLayer(control);
adornerLayer.Add(myAdorner);
_controlToAdornersMap[control] = new List<Adorner> {myAdorner};
}
private void OnMyControlMouseEnterOrLeave(object sender, MouseEventArgs e)
{
HitTestAndSetAdornersVisibility((MyControl)sender, e);
}
private void OnMyAdornerMouseEnterOrLeave(object sender, MouseEventArgs e)
{
var adorner = (Adorner)sender;
HitTestAndSetAdornersVisibility((MyControl)adorner.AdornedElement, e);
}
private void HitTestAndSetAdornersVisibility(MyControl control, MouseEventArgs e)
{
var adorners = _controlToAdornersMap[control];
var hitTestSubjects = new List<UIElement> { control }.Concat(adorners);
var hit = hitTestSubjects.Any(i => VisualTreeHelper.HitTest(i, e.GetPosition(i)) != null);
SetAdornersVisibility(adorners, hit ? Visibility.Visible : Visibility.Collapsed);
}
private static void SetAdornersVisibility(IEnumerable<Adorner> adorners, Visibility visibility)
{
if (adorners != null)
foreach (var adorner in adorners)
adorner.Visibility = visibility;
}