我目前正在开发某种具有“弹出”模式的菜单 - 意味着它仍然处于紧凑模式(仅约60px宽度),直到你鼠标悬停为止。主题是非常棘手的,因为你无法直接设置控件的宽度,并设置它会导致固定的大小(这不是我想要的)。
我的目标是让控件具有基于它的子项和最大值的动态大小。它的父母可用空间。
我的理论:一旦尺寸发生变化,就会调用测量来测量最大可用空间(远远超过将要使用的空间)。下一步是安排。使用参数 arrangeBounds 调用 ArrangeOverride(),该参数等于所需的大小。
现在我缓存此值,如果它与 ActualSize 属性不同,我会从 ActualSize 到 arrangeBounds.Width 启动动画。该方法本身确实返回了像return base.ArrangeOverride(new Size(WidthWrapper, arrangeBounds.Height));
到目前为止,我已经有了这个(并且它部分正常工作 - WidthWrapper只是一个DependencyProperty):
protected override Size ArrangeOverride(Size arrangeBounds)
{
if (Math.Abs(WidthWrapper) < 0.01)
WidthWrapper = arrangeBounds.Width;
if (Math.Abs(arrangeBounds.Width - ActualWidth) > 0.01)
{
if (_started & (Math.Abs(arrangeBounds.Width - _cache) < 0.01))
return base.ArrangeOverride(new Size(WidthWrapper, arrangeBounds.Height));
if (Math.Abs(arrangeBounds.Width - WidthWrapper) < 0.01)
return base.ArrangeOverride(new Size(WidthWrapper, arrangeBounds.Height));
if (_started & !_isExpanding)
{
Console.WriteLine("Re-Animate");
// Change value
if (_cache < arrangeBounds.Width)
_isExpanding = true;
_cache = arrangeBounds.Width;
_board.Stop(this);
_board.Children.Clear();
_anim = new DoubleAnimation(WidthWrapper, arrangeBounds.Width,
new Duration(TimeSpan.FromSeconds(0.8)))
{
EasingFunction = new QuadraticEase() {EasingMode = EasingMode.EaseInOut}
};
_board.Children.Add(_anim);
Storyboard.SetTarget(_anim, this);
Storyboard.SetTargetProperty(_anim, new PropertyPath(WidthWrapperProperty));
_board.Begin(this);
return base.ArrangeOverride(new Size(WidthWrapper, arrangeBounds.Height));
}
if (!_started)
{
if (_cache < arrangeBounds.Width)
_isExpanding = true;
_cache = arrangeBounds.Width;
_anim = new DoubleAnimation(WidthWrapper, arrangeBounds.Width,
new Duration(TimeSpan.FromSeconds(1.5)))
{
EasingFunction = new QuadraticEase() {EasingMode = EasingMode.EaseInOut}
};
_board.Children.Add(_anim);
Storyboard.SetTarget(_anim, this);
Storyboard.SetTargetProperty(_anim, new PropertyPath(WidthWrapperProperty));
_board.Begin(this, true);
_started = true;
}
}
Size animatedSize = new Size(WidthWrapper, arrangeBounds.Height);
return base.ArrangeOverride(animatedSize);
}
启动测试项目时,菜单以几乎全尺寸开始,你会看到它的一部分从右边“淡入” - 看起来非常酷。现在的问题是,当我切换到紧凑模式时,没有动画。它立即变成~61px宽。当我将鼠标悬停在它上面时,你会看到它在扩展但是闪烁并随机跳回到之前的大小。
问题显然是使用这种方法错误地控制了控件。在做这个动画时,它看起来有点偏离右侧。因此,不再检测到鼠标悬停,并且它试图动画回到紧凑的尺寸。这种情况经常发生,直到动画完成并最终达到完整大小(如果它完全达到)。
它的父母似乎是某种安置问题。我在这里加了一个GIF,所以你可以看到我的意思。
PS:我禁用了“flyout”模式,但是即使从普通模式切换到紧凑模式也有问题(虽然它部分有效但看起来很不错)。任何想法如何解决这个问题,使其顺利扩展,没有任何闪烁和其他问题?专业UI库具有例如对接窗口,其在取消固定时快速淡出。我想以某种方式将这种效果应用到我的菜单中。我认为这是可能的,因为我已经接近了 - 但显然WPF不支持它没有一点诡计。