【问题标题】:WPF TabControl cannot switch tabs when hosting DataGrid托管 DataGrid 时 WPF TabControl 无法切换选项卡
【发布时间】:2019-11-13 12:11:04
【问题描述】:

在默认的TabControl 中,您可以使用Ctrl+Tab 切换选项卡,但是如果其中一个选项卡包含DataGrid,则所有选项卡都会中断。例如,如果我有一个简单的TabControl,只包含文本框:

<TabControl>
    <TabItem Header="Tab1">
        <TextBox/>
    </TabItem>
    <TabItem Header="Tab2">
        <TextBox/>
    </TabItem>
    <TabItem Header="Tab3">
        <TextBox/>
    </TabItem>
</TabControl>

反复按Ctrl+Tab,当前Tab会循环:

Tab1 > Tab2 > Tab3 > Tab1 > ...等

但如果我将几乎任何 DataGrid 放在中间的选项卡之一中,例如:

...    
<TabItem Header="Tab2"> <!--replacing 2nd tab content-->
    <TabItem.Resources>
        <x:Array x:Key="Items" Type="{x:Type Run}">
            <Run Text="Foo"/>
            <Run Text="Bar"/>
            <Run Text="Baz"/>
        </x:Array>
    </TabItem.Resources>
    <DataGrid ItemsSource="{StaticResource Items}"/>
</TabItem>

Ctrl+Tab 会卡住,无法通过所述 Tab:

Tab1 > Tab2 > Tab1 > Tab2 > ...等

我该如何解决这个问题?


我在DataGrid 上尝试了IsTabStop="False" 以及KeyBoardNavigation 属性的几种组合,所有这些都没有效果或适得其反。


Edit(2): 问题似乎主要出现在DataGridTabItem第一个 可聚焦子元素时,例如内容:

<StackPanel>
    <TextBox/>
    <DataGrid ItemsSource="{StaticResource Items}"/>
</StackPanel>

几乎有效,直到用户选择DataGrid。如果接下来选择网格 Ctrl+Tab 则返回到第一个 Tab 而不是下一个。

【问题讨论】:

  • 不确定你在说什么,我的 ctrl/tab 在其中一个选项卡中有 DG 时工作正常,可能是其他原因造成的!
  • @SamTheDev 我正在使用在 Windows 10 机器上运行的空 4.7.2 项目,问题中只包含 XAML 代码(粘贴为 Window 内容),您的设置是什么?
  • 我猜也一样,只是粘贴了您的代码,三个标签,其中第三个是带有网格的标签,.net 4.7.2 on a win 10 1903。
  • @SamTheDev 尝试将网格放在第二个选项卡中。循环在遇到第一个网格时停止/重新启动 - 如果网格在最后一个选项卡中,您将无法判断它是在那里停止还是循环正常完成。
  • 嗯,有趣,现在我看到了问题!

标签: c# wpf datagrid tabcontrol


【解决方案1】:

看起来这是一个焦点问题,当Datagrid 获得焦点时,它会从TabControl 中丢失,因此只要在DataGrid 所在的位置按下 ctrl/tab 时,就以编程方式设置焦点:

 <TabControl  x:Name="TabCtrl">
        <TabItem Header="Tab1" x:Name="Tab1" >
            <TextBox/>
        </TabItem>
        <TabItem Header="Tab3" x:Name="Tab2"  PreviewKeyDown="UIElement_OnPreviewKeyDown">
            <TabItem.Resources>
                <x:Array x:Key="Items" Type="{x:Type Run}">
                    <Run Text="Foo"/>
                    <Run Text="Bar"/>
                    <Run Text="Baz"/>
                </x:Array>
            </TabItem.Resources>
            <DataGrid ItemsSource="{StaticResource Items}" />
        </TabItem>
        <TabItem Header="Tab2"  x:Name="Tab3">
            <TextBox/>
        </TabItem>
    </TabControl>

处理程序:

 private void UIElement_OnPreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Tab &&
            (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && sender is TabItem)
        {
            TabCtrl.Focus();
        }
    }

【讨论】:

  • 看起来不错,我会限制更多(检查源和发件人之间是否有任何焦点范围),但看起来这是问题的根源。另外,这可以很容易地变成附加行为并默认固定在所有 TabControls 上。
【解决方案2】:

你试过了吗

IsTabStop="False"

在您的控件上。这可以防止焦点进入那个控件?用户仍然可以手动单击网格以获得焦点(或其他控件),但如果没有,它将忽略尝试将焦点移至该控件。

只是为了扩展 IsTabStop,您可能想尝试将其包装到用户控件中并在用户控件处停止,这样它就不会进入其中的任何内容...例如

<UserControl IsTabStop="false">
   <DataGrid>
      …
   </DataGrid>
</UserControl>

【讨论】:

  • 抱歉,忘记在问题中包含它。我已经尝试过了,DataGrid 上的IsTabStop="False"(以及几个 KeyboardNavigation.XXX=YYY 组合)没有效果。在每个控件上都设置它是不可取的(没有控件的 Tab 应该在 TabItems 中工作),但尝试这样做会使它的行为更加怪异:新顺序是 Tab1 > Tab2 > Tab1 > Tab2 > Tab3
  • @wondra,查看修订版,尝试包装到用户控件中?
  • 唉,从来没有改变过。此外,即使它最初可以工作,我认为如果 DataGrid 曾经与鼠标交互过,它仍然无法正常工作,不是吗?
猜你喜欢
  • 2011-09-01
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多