我有几个按钮,我希望它们在光标定位在指定时间之后执行某些操作。在这种情况下,他们应该只在文本框中写下他们的内容。
这是计时器:
private static System.Timers.Timer myTimer =
new System.Timers.Timer(1500);
这是按钮使用MouseEnter事件执行的方法:
private void keysHover(object sender, EventArgs e)
{
myTimer.Elapsed += delegate { keysHoverOK(sender); };
myTimer.Enabled = true;
}
如果Timer结束,这就是执行的内容:
private void keysHoverOK(object sender)
{
this.Dispatcher.Invoke((Action)(() =>
{
txtTest.Text += (sender as System.Windows.Controls.Button).Content.ToString();
}));
myTimer.Enabled = false;
}
我不太明白为什么会发生这种情况,但是每当其中一个按钮完成Timer时,keysHoverOK
方法就会写出与已悬停的字符一样多的字符。例如,如果我将鼠标悬停在按钮A
上,则会写入A
,如果我将鼠标悬停在按钮B
上,则会写入AB
,从而获得AAB
1}}写在文本框上等等,句子执行次数与其他按钮执行keysHover方法一样多,即使他们没有完成Timer本身,就像他们的内容被保存在某个地方。当然,我想按钮所做的只是编写内容和内容。所以你知道我做错了什么吗?
答案 0 :(得分:0)
你的意思是MouseEnter
事件吗?我不知道WPF中有任何MouseOver
事件。
如果没有a good, minimal, complete code example,就无法确定问题是什么。但是,根据您共享的少量代码和问题描述,您的主要问题似乎是您与多个控件共享一个Timer
对象。当一个控件订阅Timer.Elapsed
事件时,它永远不会取消订阅,这加剧了这一点。因此,如果另一个控件启用了计时器(也订阅了该事件),则在计时器间隔过去时会通知两个控件。
即使是单个控件也存在问题,因为每次引发MouseEnter
事件时它都会自行订阅该事件。
修复是禁用计时器并在鼠标离开控件边界时或在计时器间隔结束时取消订阅事件。这可能看起来像这样:
private EventHandler _timerElapsedHandler;
// Subscribed to the MouseEnter event
private void keysHover(object sender, EventArgs e)
{
_timerElapsedHandler = delegate { keysHoverOK(sender); };
myTimer.Elapsed += _timerElapsedHandler;
myTimer.Enabled = true;
}
// Subscribed to the MouseLeave event
private void keysLeave(object sender, EventArgs e)
{
DisableTimer();
}
private void keysHoverOK(object sender)
{
this.Dispatcher.Invoke((Action)(() =>
{
txtTest.Text += (sender as System.Windows.Controls.Button).Content.ToString();
}));
DisableTimer();
}
private void DisableTimer()
{
myTimer.Elapsed -= _timerElapsedHandler;
myTimer.Enabled = false;
_timerElapsedHandler = null;
}
其他评论:
as
。仅当引用可以合法地使用与您检查的类型不同时才使用as
。当它总是应该是您要检查的类型时使用强制转换。这样,如果您有错误,您将获得一个有意义的例外,而不仅仅是一些NullReferenceException
Content.ToString()
值并存储它。然后,我将使用一个命名方法,而不是对委托实例使用匿名方法,该方法只使用存储的string
值附加到Text
属性。您可以按名称订阅和取消订阅指定的方法;委托类型做正确的事情,即使它使用不同的委托实例进行订阅和取消订阅。Timer
实例。然后,您不必在鼠标事件发生时订阅或取消订阅;只是在初始化期间订阅。DependencyProperty
,或实现INotifyPropertyChanged
),并将其绑定到{{1}而不是直接操纵该属性。答案 1 :(得分:0)
我假设你说:
这是按钮使用MouseOver事件执行的方法:
您可能是指MouseEnter
事件?
从我看到的内容:
代码段myTimer.Elapsed += delegate { keysHoverOK(sender); };
将另一个委托添加到已添加的委托列表中。它不会只用一个代表替换列表。
如果在计时器过去之前离开按钮,则需要使用减号运算符(myTimer.Elapsed -= ....
)从计时器已用事件中删除委托,然后停止计时器。这里有一个问题,你已经创建了一个匿名方法,所以你需要: -
或
或者可能是最简单的menthod