3

タブ オーダーが設定されたすぐに使えるコントロールを含む WPF ページがあります。

境界線/グリッド/テキスト ボックス/2 つの Repeatbuttons (上/下) を含むカスタム コントロール (NumericSpinner) があります。

2 つの問題:

1) カスタム セレクター コントロールのテキスト ボックスにいるとき、そこからタブでページ上の他のコントロールに移動できません。ただし、上下の矢印のいずれかをクリックした後、タブで他のコントロールに移動できます。

2) カスタム コントロールのテキスト ボックスにタブで移動できません。すべてのコントロールをタブで移動した後でのみ、カーソルがテキスト ボックスに表示されます (タブ アウトできません)。

環境:

<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 とコード ビハインド ファイルで構成されます。

すべてのコントロールを含む親 xaml ページは動的に読み込まれ、コード ビハインドは含まれません。

カスタム コントロールのコンストラクターで、テストとして次のように設定しました。

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

4回目にタブを押すと、実際にカーソルがテキストフィールドに移動しますが、タブから出ることができません。

これを念頭に置いて、最初のステップは、コントロールの分離コードで設定されるタブ オーダー番号を渡すことができるコントロール パラメーターを作成することです。

CustomTabIndex プロパティを作成しました。

/// <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" を設定しようとすると、次のエラーが表示されます。

プロパティ「CustomTabIndex」はタイプ「NumericSpinner」で見つかりませんでした。

いくつかの支援をいただければ幸いです。

4

5 に答える 5

6

最初のものに対する答えがあります... CustomControl の静的コンストラクターに次を追加します

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

これにより、コントロールにタブで出入りできるようになり、カスタム コントロールの各子にタブ インデックスを設定できるようになります。

2 番目の質問については、同じことを解明するために取り組んでいます。カスタム コントロールに Focusable = False があることが原因だと思います。ただし、これを true に設定すると、実際の子ではなくコントロールがフォーカスされます。必要になるのは、GotFocus イベントの CustomControl のイベント ハンドラーだと思います。コントロールがフォーカスを得たら、

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

フォーカスを子要素に移動する必要があります。

適切な方法を見つけたら、フォローアップを投稿します。

アップデート

それでは、2番目のポイントについて。

コントロールの静的コンストラクターで focusable を false に設定し、TabNavigationProperty をそのように設定してください。

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

これにより、コントロールが期待どおりに機能し、コントロールとすべての子のタブ オーダーが尊重されます。スタイルで Focusable または TabNavigation プロパティを設定しないようにしてください。

ラウル

于 2011-01-20T17:41:39.390 に答える
4

完全な解決策はありませんが、次の 4 つの点でタブの循環をチェックする必要があります。

  • TabIndex はタブ順序を定義します
  • IsTabStop は、コントロールをタブ循環に使用する必要があるかどうかを示します
  • FocusManager.IsFocusScopeは、要素が独自のフォーカス領域を構築する場合、
  • Focusableは、UIElement がフォーカスを取得できるかどうかを示します。

IsFocusScope は面白いだろうと想像できました。

于 2011-01-18T19:25:25.967 に答える
0

Raul は、カスタム コントロールのテキスト ボックスにタブで移動できるという主要な問題に答えました。2 つ目の問題は、テキスト ボックスからタブで移動できないことでした。

このコントロールの問題は、そのテキスト ボックスに keypress ハンドラーが含まれていることでした。

PreviewKeyDown="valueText_PreviewKeyDown"

ハンドラーは、テキスト ボックス内で特定のキーを押すことのみを許可します。

/// <summary>
/// Since this event handler traps keystrokes within the control, in order to facilitate tabbing order, allowing the 
/// tab key press must be enabled
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void valueText_PreviewKeyDown(object sender, KeyEventArgs e)
{ 
    KeyConverter converter = new KeyConverter();
    string key = converter.ConvertToString(e.Key);
    int index = ((TextBox)sender).CaretIndex;
    if (key != null)
    {
        if (AllowNegativeValues && (e.Key == Key.Subtract || e.Key == Key.OemMinus))
        {
            e.Handled = (valueText.Text.Contains('-') || index > 0) == true;
        }
        else if (AllowDecimal && (e.Key == Key.OemPeriod || e.Key == Key.Decimal))
        {
            e.Handled = valueText.Text.Contains('.') == true;
        }
        else
            e.Handled = ((((e.Key >= Key.D0) && (e.Key <= Key.D9) && (e.KeyboardDevice.Modifiers != ModifierKeys.Shift))
                            || ((e.Key >= Key.NumPad0) && (e.Key <= Key.NumPad9) && (e.KeyboardDevice.Modifiers != ModifierKeys.Shift))
                            || e.Key == Key.Left || e.Key == Key.Right
                            || e.Key == Key.Back || e.Key == Key.Delete 
                            || e.Key == Key.Tab) == false);             
    }
    else
        e.Handled = true;
}

許容される TAB キーストロークを追加するだけで、カスタム コントロールは正常に動作します。

e.Key == Key.Tab
于 2011-01-21T16:15:48.140 に答える
0

HaxElit の答えは、次のようにラベルを使用してコントロールに焦点を当てたい場合を除いて機能しますAlt + hotkey

<!-- Alt + C selects numCount -->
<Label Target="{Binding ElementName=numCount}">Elements _Count:</Label>
<local:NumericSpinner x:Name="numCount"/>

したがって、私の最終的な解決策は次のとおりです。

static NumericSpinner()
{
    // Next line prevents focusing our wrapper parent control. The problem with that is that
    // it prevents Label controls to select our control by Alt+<hotkey>
    //FocusableProperty.OverrideMetadata(typeof(NumericSpinner), new FrameworkPropertyMetadata(false));

    // Next line specifies that the children controls have their own tab subtree so a deep
    // traversal is performed when our control is focused
    KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(NumericSpinner), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local));
}

// our wrapper control is focused invisibly. We must relocate the focus.
protected override void OnGotFocus(RoutedEventArgs e)
{
    base.OnGotFocus(e);

    // Next line moves the focus either forward (to out first inner child)
    // or backward if Shift+TAB is pressed (to the previous control)
    MoveFocus(new TraversalRequest(Keyboard.IsKeyDown(Key.Tab) && (Keyboard.Modifiers & ModifierKeys.Shift) != 0 ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next));
}
于 2016-06-16T14:24:17.350 に答える
0

選択した回答のイベントを使用してみましたが、うまくいきません。最初の回答が実際に選択されGotFocusていても、タブ ナビゲーションが完全に無効になっているようです。 私にとってうまくいったのは、イベントを使用し、そこで同じコマンドを使用することでした: TabStop
WindowActivated

MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

誰かの役に立てば幸いです。

于 2011-12-06T09:45:50.443 に答える