我在WPF中制作了一个带有多个按钮的面板。 当鼠标进入某个按钮时,新按钮会出现,并在鼠标离开1000毫秒后消失。
但是我有一个奇怪的行为:在某些情况下,每次使用后1000毫秒会越来越短。
计时器事件
private void TimerEventProcessorForButtonA(Object myObject, EventArgs myEventArgs)
{
_myTimerForButtonA.Stop();
miniButton1.Visibility = System.Windows.Visibility.Hidden;
}
private void TimerEventProcessorForButtonB(Object myObject, EventArgs myEventArgs)
{
_myTimerForButtonB.Stop();
miniButton2.Visibility = System.Windows.Visibility.Hidden;
}
WaitTime函数调用计时器:
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerButtonA.Tick += new EventHandler(TimerEventProcessorForForButtonA);
_myTimerForForButtonA.Interval = givenTime;
_myTimerForForButtonA.Start();
}
public void WaitThisTimeAndHideMiniButton2(int givenTime)
{
_myTimerForButtonB = new System.Windows.Forms.Timer();
_myTimerForButtonB.Tick += new EventHandler(TimerEventProcessorForForButtonB);
_myTimerForForButtonB.Interval = givenTime;
_myTimerForForButtonB.Start();
}
离开按钮时的事件:
private void buttonA_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton1(1000); // hide minibuttons
}
private void buttonB_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush) new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton2(1000);
}
如代码中所述,我有buttonA和buttonB。当我输入buttonA时,出现miniButton1-鼠标离开事件后1000毫秒它将消失。 对于buttonB来说,这也揭示了miniButton2。
如果我只进入和离开buttonB,一切都正确。与ButtonA相同。 问题:如果我输入/退出按钮A和B,那么这1000毫秒就会越来越短。 miniButton的消失也出现在我离开按钮A和B之前。也发生在我离开按钮之前。
所有的行为都像是计时器彼此混淆一样。 你知道如何解决吗?
答案 0 :(得分:1)
每次触发Timer
事件时,您将重新创建一个新的MouseLeave
,如果您碰巧在1000ms内两次触发了该事件,则将在之前重新创建一个新的Timer
执行前一个Tick
的{{1}}事件,这将使前一个Timer
无限期运行。
这是在1000毫秒内两次触发Timer
事件时发生的情况:
MouseLeave
我能够通过在1) MouseLeave: _myTimerForButtonA is assigned a new Timer instance (ie: Timer1), Tick event registered.
2) MouseLeave: _myTimerForButtonA is assigned a new Timer instance (ie: Timer2), Tick event registered.
3) Timer1.Tick event fires TimerEventProcessorForButtonA, whichs stops _myTimerForButtonA which points to Timer2.
4) Timer2.Tick event fires TimerEventProcessorForButtonA, whichs stops _myTimerForButtonA which points to Timer2 (and is already stopped).
5) Timer1.Tick event fires TimerEventProcessorForButtonA indefinitely, because Timer1 is not referenced anymore and no one will ever call `Stop` on it.
事件中停止计时器来修正您的代码
MouseEnter
如您的帖子评论中所述,您不应每次都创建一个新的 private void TimerEventProcessorForButtonA(Object myObject, EventArgs myEventArgs)
{
Debug.WriteLine("TimerEventProcessorForButtonA");
_myTimerForButtonA.Stop();
_myTimerForButtonA.Dispose();
miniButton1.Visibility = System.Windows.Visibility.Hidden;
}
private void TimerEventProcessorForButtonB(Object myObject, EventArgs myEventArgs)
{
Debug.WriteLine("** TimerEventProcessorForButtonB");
_myTimerForButtonB.Stop();
_myTimerForButtonB.Dispose();
miniButton2.Visibility = System.Windows.Visibility.Hidden;
}
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerForButtonA.Tick += new EventHandler(TimerEventProcessorForButtonA);
_myTimerForButtonA.Interval = givenTime;
_myTimerForButtonA.Start();
}
public void WaitThisTimeAndHideMiniButton2(int givenTime)
{
_myTimerForButtonB = new System.Windows.Forms.Timer();
_myTimerForButtonB.Tick += new EventHandler(TimerEventProcessorForButtonB);
_myTimerForButtonB.Interval = givenTime;
_myTimerForButtonB.Start();
}
private void buttonA_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton1(1000); // hide minibuttons
}
private void buttonB_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton2(1000);
}
private void buttonA_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_myTimerForButtonA?.Enabled == true)
_myTimerForButtonA.Stop();
miniButton1.Visibility = System.Windows.Visibility.Visible;
}
private void buttonB_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_myTimerForButtonB?.Enabled == true)
_myTimerForButtonB.Stop();
miniButton2.Visibility = System.Windows.Visibility.Visible;
}
,并且应该在处理完毕后立即将其丢弃。另外,除非确实有必要,否则在WPF项目中引用Forms是一个坏主意,这种情况很少。您可能需要阅读关于Storyboard的UI动画。
答案 1 :(得分:0)
所以基本上这是在鼠标离开时发生的:
creating the timer
starting the timer
这会在计时器到期时发生:
stopping the timer
因此,如果鼠标反复进入并留下一个按钮,它将继续创建和启动新计时器。导致多个计时器同时运行。
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
if(_myTimerForButtonA != null && _myTimerForButtonA.Enabled)
{
_myTimerForButtonA.Stop();
}
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerButtonA.Tick += new EventHandler(TimerEventProcessorForForButtonA);
_myTimerForForButtonA.Interval = givenTime;
_myTimerForForButtonA.Start();
}
尽管评论中提到的问题更多,但这应该可以解决该问题。