WPF选项卡顺序与自定义控件? [英] WPF tab order with custom controls?

查看:97
本文介绍了WPF选项卡顺序与自定义控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WPF页面,其中包含多个具有按Tab键顺序设置的开箱即用控件.

I have a WPF page that contains several out of the box controls with the tab order set.

我有一个自定义控件(NumericSpinner),其中包含:边框/网格/文本框/2重复按钮(上/下).

I have a custom control (NumericSpinner) that contains: border/grid/text box/2 Repeatbuttons (up/down).

两个问题:

1)当我在自定义选择器控件的文本框中时,无法将其跳出页面上的其他控件.但是,单击上/下箭头之一后,我可以切换到其他控件.

1) when I am in the textbox for the custom selector control, I cannot tab out of it to other controls on the page. However after clicking on one of the up/down arrows, I am able to tab over to other controls.

2)我无法按顺序进入自定义控件的文本框.只有在我浏览完所有控件之后,光标才能进入文本框(并且不能跳出).

2) I am unable to tab into the textbox of the custom control in order. It is only after I have tabbed through all of the controls, that the cursor lands in the text box (and cannot tab out).

上下文:

<ComboBox Margin="97,315,21,0" Name="txtdweldatcdu" Style="{StaticResource fieldComboBoxStyle}" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left" VerticalAlignment="Top" TabIndex="10" />
    <WpfControls:NumericSpinner Margin="97,338,21,0" Name="txtdweldatpctcomplete" HorizontalAlignment="Left" VerticalAlignment="Top" AllowNegativeValues="True" MaxValue="100" TabIndex="11" />
    <ComboBox Margin="97,363,21,0" Name="txtdweldatclass" Style="{StaticResource fieldComboBoxStyle}" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left" VerticalAlignment="Top" TabIndex="12" />

自定义控件的部分:

 <Border BorderThickness="1" BorderBrush="Gray" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="20" Width="117">
        <Grid Margin="0">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="98"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox Name="valueText" 
                     BorderThickness="0" 
                     Grid.RowSpan="2"
                     Style="{StaticResource spinnerTextBoxStyle}"
                     PreviewKeyDown="valueText_PreviewKeyDown"
                     PreviewTextInput="valueText_PreviewTextInput"
                     TextChanged="valueText_TextChanged"
                     IsReadOnly="{Binding ElementName=Spinner, Path=IsReadOnly}"
                     Text="{Binding ElementName=Spinner, Path=Value, Mode=TwoWay}"
                     KeyboardNavigation.IsTabStop="True"
                     AcceptsTab="True"/>
            <RepeatButton Name="upButton" Style="{StaticResource spinnerRepeatButtonStyle}" Click="upButton_Click"  Grid.Column="1" Grid.Row="0" Height="10" Width="18" VerticalAlignment="Top" HorizontalAlignment="Right" HorizontalContentAlignment="Center">
                <Polygon  HorizontalAlignment="Center" Points="3,2 2,3 4,3"  Fill="Black"  Stretch="Uniform"  Stroke="Black"  StrokeThickness="0" />
            </RepeatButton>
            <RepeatButton Name="downButton" Style="{StaticResource spinnerRepeatButtonStyle}" Click="downButton_Click"  Grid.Column="1" Grid.Row="1" Height="10" Width="18" VerticalAlignment="Top" HorizontalAlignment="Right" HorizontalContentAlignment="Center">
                <Polygon  HorizontalAlignment="Center" Points="2,2 4,2 3,3"  Fill="Black"  Stretch="Uniform"  Stroke="Black"  StrokeThickness="0" />
            </RepeatButton>
        </Grid>
    </Border>

自定义控件由xaml和代码隐藏文件组成.

The custom control consists of the xaml and code-behind file.

包含所有控件的父级xaml页面是动态加载的,并且不包含任何代码隐藏.

Parent xaml page, containing all controls is loaded dynamically and contains no code-behind.

在自定义控件的构造函数中,我将以下内容设置为测试:

In the constructor for the custom control, I have set the following as a test:

    valueText.TabIndex = 3;
    this.TabIndex = 3;

我第四次使用Tab键时,实际上将光标移到了文本字段中,但是我无法跳出它.

The fourth time I tab, I actually get the cursor into the text field, however I cannot tab out of it.

牢记这一点,第一步是创建一个控件参数,我可以传递一个制表符顺序号,该顺序号将在控件的背后代码中设置.

With this in mind, the first step would be to create a control parameter that I can pass a tab order number that would get set in the control's codebehind.

我创建了一个CustomTabIndex属性:

I created a CustomTabIndex property:

/// <summary>
/// Custom tab index property
/// </summary>
public int CustomTabIndex
{
    get { return (int)GetValue(CustomTabIndexProperty); }
    set { SetValue(CustomTabIndexProperty, value); }
}

public static readonly DependencyProperty CustomTabIndexProperty = 
    DependencyProperty.Register("CustomTabIndex", typeof(int), typeof(NumericSpinner));

在xaml中,当我尝试设置CustomTabIndex ="3"时,收到错误消息:

And in the xaml, when I try to set CustomTabIndex="3", I receive the error:

属性"CustomTabIndex"不是 在"NumericSpinner"类型中找到.

The property 'CustomTabIndex' was not found in type 'NumericSpinner'.

一些帮助将不胜感激.

推荐答案

我对第一个答案... 在CustomControl的静态构造函数中,添加以下内容

I have an answer to the first one... In your static constructor for your CustomControl add the following

KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(NumericSpinner), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local));

这应该允许您在控件中签入和签出,并允许您为自定义控件的每个子控件设置一个标签索引.

That should let you tab in and out of the control and allow you to set a tab index for each of the children of your custom control.

关于您的第二个问题,我正在努力弄清楚同一件事.我认为这必须归因于您的自定义控件具有Focusable = False.但是将其设置为true将使控件获得焦点,而不是实际的孩子.我认为可能需要在GotFocus事件的CustomControl上使用事件处理程序.当控件获得焦点时,请执行

As for your second question, I'm working on figuring out the same thing. I think it has to due with the fact that your custom control has Focusable = False. But setting this to true will make the control get focus not the actual children. I think what might be required is an event handler on your CustomControl for the GotFocus event. When the control gets focus then do a

this.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

这应该将焦点移到子元素上.

and that should move the focus to the child elements.

找出正确的方法后,我将进行后续跟踪.

I'll post a follow up when I figure out the proper way of doing it.

更新

第二点.

请确保在控件的静态构造函数中将focusfocus设置为false,并且将TabNavigationProperty设置为此类

Make sure you set focusable to false and the TabNavigationProperty like so in the static constructor for your control

FocusableProperty.OverrideMetadata(typeof(NumericSpinner), new FrameworkPropertyMetadata(false));
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(NumericSpinner), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local));

这将使控件能够按预期工作,并遵守控件以及所有子控件上的Tab键顺序.确保在您的样式中没有设置Focusable或TabNavigation属性.

This will allow the control to work as expected and respect the Tab Order on the control and also all the children. Make sure that in your style you don't set the Focusable or TabNavigation properties.

劳拉

这篇关于WPF选项卡顺序与自定义控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆