如何让SizeChanged事件等待布尔值变更或OnMouseLeave触发?
解决方案
可以通过标记状态+延迟触发的方式实现需求,核心思路是先记录布局尺寸变化的执行需求,等鼠标移出控件后再执行Resize逻辑,以下是两种常用实现方式:
方法一:状态标记+事件联动
- 在控件类中定义两个布尔标记,分别记录「是否需要执行Resize」和「当前鼠标是否在控件上」:
private bool _needResize = false; private bool _isMouseOver = false;
- 替换原有的SizeChanged直接绑定,改为自定义处理方法,同时绑定鼠标进出事件:
// 移除原直接绑定 // layout.SizeChanged += parentToggleBox.Resize; // 替换为自定义逻辑 layout.SizeChanged += Layout_SizeChanged; layout.MouseEnter += Layout_MouseEnter; layout.MouseLeave += Layout_MouseLeave;
- 实现对应的事件处理逻辑:
private void Layout_SizeChanged(object sender, SizeChangedEventArgs e) { if (!_isMouseOver) { // 鼠标不在控件上,直接执行Resize parentToggleBox.Resize(sender, e); } else { // 鼠标仍在控件上,标记需要执行Resize _needResize = true; } } private void Layout_MouseEnter(object sender, MouseEventArgs e) { _isMouseOver = true; } private void Layout_MouseLeave(object sender, MouseEventArgs e) { _isMouseOver = false; // 检查是否有等待执行的Resize需求 if (_needResize) { // 传递最新的尺寸参数执行Resize,参数可根据实际需求调整 parentToggleBox.Resize(layout, new SizeChangedEventArgs(layout.ActualWidth, layout.ActualHeight, layout.ActualWidth, layout.ActualHeight)); _needResize = false; } }
方法二:异步等待MouseLeave事件(适合复杂场景)
如果需要更灵活的异步控制,可以用TaskCompletionSource等待MouseLeave触发后再执行Resize:
- 定义一个辅助方法用于等待鼠标移出:
private async Task WaitForMouseLeave(UIElement element) { var tcs = new TaskCompletionSource<bool>(); void Handler(object s, MouseEventArgs e) { element.MouseLeave -= Handler; tcs.TrySetResult(true); } element.MouseLeave += Handler; await tcs.Task; }
- 修改SizeChanged的处理逻辑为异步方法:
layout.SizeChanged += async (sender, e) => { // 若鼠标当前在控件上,等待移出后再执行 if (layout.IsMouseOver) { await WaitForMouseLeave(layout); } // 执行Resize逻辑 parentToggleBox.Resize(sender, e); };
注意事项
- 方法一中,MouseLeave触发时传递的
SizeChangedEventArgs可根据Resize方法的实际参数需求调整,若不需要具体尺寸信息,也可传入null。 - 方法二中,需确保MouseLeave事件处理程序被正确移除,避免内存泄漏。
内容的提问来源于stack exchange,提问作者user11095285
相关产品推荐
相关产品推荐

