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

如何阻止UWP中按钮禁用时自动切换焦点

解决按钮禁用时焦点跳转到下一个Grid项的问题

首先修正代码中的关键问题:由于sampleGridItem是通过ObservableCollection生成多个实例,直接通过名称SampleButton引用按钮只会作用于单个实例,正确做法是通过sender获取当前点击的按钮:

修正后的后台C#代码

private void buttonClickEvent(object sender, RoutedEventArgs e)
{
    Button clickedButton = sender as Button;
    if (clickedButton == null) return;

    clickedButton.IsEnabled = false;
    // 执行你的业务操作
    clickedButton.IsEnabled = true;
}

以下是几种解决焦点跳转问题的方案:


方案1:禁用按钮前将焦点转移到当前Grid项

让父级sampleGridItem变为可聚焦元素,在禁用按钮前将焦点切换到该Grid,避免焦点跳转到其他项:

修改后的XAML

<Grid>
    <Grid x:Name="sampleGridItem" Focusable="True">
        <Button Click="buttonClickEvent" />
        <TextBlock x:Name="SampleTextBlock"/>
    </Grid>
</Grid>

更新后的点击事件代码

private void buttonClickEvent(object sender, RoutedEventArgs e)
{
    Button clickedButton = sender as Button;
    if (clickedButton == null) return;

    // 获取当前按钮所在的Grid项
    Grid parentGrid = clickedButton.Parent as Grid;
    if (parentGrid != null)
    {
        // 将焦点转移到当前Grid项
        parentGrid.Focus();
    }

    clickedButton.IsEnabled = false;
    // 执行你的操作(如果是异步操作,使用await)
    clickedButton.IsEnabled = true;

    // 可选:操作完成后将焦点恢复到按钮
    clickedButton.Focus();
}

方案2:拦截按钮失去焦点事件

通过PreviewLostFocus事件阻止按钮在被禁用时失去焦点:

修改后的XAML

<Grid>
    <Grid x:Name="sampleGridItem">
        <Button Click="buttonClickEvent" PreviewLostFocus="SampleButton_PreviewLostFocus" />
        <TextBlock x:Name="SampleTextBlock"/>
    </Grid>
</Grid>

后台代码添加事件处理

private bool _preventFocusLoss = false;

private void buttonClickEvent(object sender, RoutedEventArgs e)
{
    Button clickedButton = sender as Button;
    if (clickedButton == null) return;

    _preventFocusLoss = true;
    clickedButton.IsEnabled = false;
    _preventFocusLoss = false;

    // 执行你的操作
    clickedButton.IsEnabled = true;
}

private void SampleButton_PreviewLostFocus(object sender, RoutedEventArgs e)
{
    // 仅在禁用按钮时阻止焦点转移
    if (_preventFocusLoss)
    {
        e.Handled = true;
    }
}

方案3:异步操作时的焦点管理

如果你的操作是异步的,使用async/await并保存当前焦点,操作完成后恢复:

private async void buttonClickEvent(object sender, RoutedEventArgs e)
{
    Button clickedButton = sender as Button;
    if (clickedButton == null) return;

    // 保存当前焦点元素
    IInputElement currentFocus = Keyboard.FocusedElement;

    clickedButton.IsEnabled = false;
    try
    {
        // 执行异步操作
        await Task.Run(() => YourAsyncOperation());
    }
    finally
    {
        clickedButton.IsEnabled = true;
        // 恢复焦点到原来的元素
        currentFocus?.Focus();
    }
}

额外优化:限制Grid项内的键盘导航

在sampleGridItem上设置键盘导航模式,确保Tab键不会跳转到其他Grid项:

<Grid x:Name="sampleGridItem" Focusable="True" KeyboardNavigation.TabNavigation="Local">
    <!-- 控件内容 -->
</Grid>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:02:35