You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中如何在Unfocused事件处理器内获取新获焦元素

解决方案:判断新获焦元素类型以控制Entry焦点

在MAUI的Unfocused事件中确实无法直接获取新获焦的元素,但可以通过以下两种方法实现你的需求:

方法1:延迟遍历可视树查找当前焦点元素

因为Unfocused事件触发时,新元素的焦点可能还未完全生效,所以需要短暂延迟后,遍历整个可视树找到当前拥有焦点的元素,再判断其类型。

修改你的SearchBar.xaml.cs代码如下:

using System.ComponentModel;
using Microsoft.Maui.Controls;

namespace SomeApp.Src.Components;

public partial class SearchBar : ContentView
{
    public SearchBar()
    {
        InitializeComponent();
        SearchField.Unfocused += OnLostFocus;
    }

    private async void OnLostFocus(object sender, FocusEventArgs e)
    {
        // 短暂延迟,确保新焦点元素已完成焦点设置
        await Task.Delay(100);
        
        // 查找当前拥有焦点的元素
        var focusedElement = FindFocusedElement(Application.Current.MainPage);
        
        // 如果新焦点不是Entry,重新聚焦当前SearchField
        if (focusedElement is not Entry)
        {
            SearchField.Focus();
        }
    }

    // 递归遍历可视树查找焦点元素
    private VisualElement FindFocusedElement(VisualElement parent)
    {
        if (parent.IsFocused)
            return parent;
        
        foreach (var child in parent.Children)
        {
            if (child is VisualElement visualChild)
            {
                var focusedChild = FindFocusedElement(visualChild);
                if (focusedChild != null)
                    return focusedChild;
            }
        }
        
        return null;
    }

    public void FocusSearchField()
    {
        SearchField.Focus();
    }   
}

方法2:全局监听焦点变化,记录当前焦点元素

在应用启动时或者页面初始化时,监听所有元素的Focused事件,维护一个全局变量存储当前焦点元素,这样在Unfocused事件中可以直接读取该变量判断类型。

步骤1:在App.xaml.cs中添加全局变量和监听

namespace SomeApp;

public partial class App : Application
{
    public static VisualElement CurrentFocusedElement { get; set; }

    public App()
    {
        InitializeComponent();
        
        // 监听全局焦点变化
        FocusManager.Focused += OnGlobalFocused;
    }

    private void OnGlobalFocused(object sender, FocusEventArgs e)
    {
        CurrentFocusedElement = e.VisualElement;
    }

    protected override void OnTerminating()
    {
        // 移除监听避免内存泄漏
        FocusManager.Focused -= OnGlobalFocused;
        base.OnTerminating();
    }
}

步骤2:修改SearchBar的OnLostFocus方法

private void OnLostFocus(object sender, FocusEventArgs e)
{
    // 判断当前全局焦点元素是否为Entry
    if (App.CurrentFocusedElement is not Entry)
    {
        SearchField.Focus();
    }
}

注意事项

  • 方法1的延迟时间可根据实际情况调整,确保新焦点元素已完成焦点设置。
  • 方法2需在应用终止时移除全局监听,避免内存泄漏。

内容的提问来源于stack exchange,提问作者GorkhaDK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:00:59