Frage

In diesem Beispiel Fenstern, geht aus der ersten Textbox durch Tabbing, zur letzten Textbox und dann an den Expander-Header.

<Window x:Class="ExpanderTab.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    FocusManager.FocusedElement="{Binding ElementName=FirstField}">
    <StackPanel>
        <TextBox TabIndex="10" Name="FirstField"></TextBox>
        <Expander TabIndex="20" Header="_abc">
            <TextBox TabIndex="30"></TextBox>
        </Expander>
        <TextBox TabIndex="40"></TextBox>
    </StackPanel>
</Window>

Natürlich, ich würde dies gerne erstes Textfeld, Expander-Header gehen, dann letzte Textbox. Gibt es eine einfache Möglichkeit, einen TabIndex an den Header des Expanders?

zuweisen

Ich habe versucht, den Expander zwingt ein tabstop mit KeyboardNavigation.IsTabStop="True" zu sein, aber das macht den ganzen Expander erhalten Fokus, und die ganzen Expander reagieren nicht auf die Leertaste. Nach zwei weiteren Registerkarten, wird der Header wieder ausgewählt und ich es mit der Leertaste öffnen kann.

Edit: Ich werde eine Prämie da draußen für jedermann werfen, die mit einem saubereren Weg kommen können, dies zu tun - wenn nicht, dann rmoore, können Sie die rep haben. Vielen Dank für Ihre Hilfe.

War es hilfreich?

Lösung

Der folgende Code funktioniert auch ohne die TabIndex Eigenschaften sind sie für Klarheit über die zu erwartenden Tabulatorreihenfolge enthalten.

<Window x:Class="ExpanderTab.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" FocusManager.FocusedElement="{Binding ElementName=FirstField}">
    <StackPanel>
        <TextBox TabIndex="10" Name="FirstField"></TextBox>
        <Expander TabIndex="20" Header="Section1" KeyboardNavigation.TabNavigation="Local">
            <StackPanel KeyboardNavigation.TabNavigation="Local">
                <TextBox TabIndex="30"></TextBox>
                <TextBox TabIndex="40"></TextBox>
            </StackPanel>
        </Expander>
        <Expander TabIndex="50" Header="Section2" KeyboardNavigation.TabNavigation="Local">
            <StackPanel KeyboardNavigation.TabNavigation="Local">
                <TextBox TabIndex="60"></TextBox>
                <TextBox TabIndex="70"></TextBox>
            </StackPanel>
        </Expander>
        <TextBox TabIndex="80"></TextBox>
    </StackPanel>
</Window>

Andere Tipps

Ich habe einen Weg gefunden, aber es ist noch besser, etwas sein.


durch Mole am Expander Sehen, oder es bei der Suche ist Control durch Mischung erzeugt wird, kann man sehen, dass der Kopfteil, der Raum reagiert / Enter / Click / etc ist wirklich ein ToggleButton. Jetzt die schlechte Nachricht, da der Header des ToggleButton hat eine diffrent Layout für den erweiterten Eigenschaften des Expander nach oben / unten / links / rechts ist es bereits hat, um es durch den Expander des Control zugeordnet Stile. Das schließt uns von etwas Einfaches wie tun ein Standard ToggleButton Stil in die Ressourcen der Expander zu schaffen.

Wenn Sie den Zugriff auf den Code haben hinter oder nichts ausmacht, Codebehind auf die Ressource Wörterbuch fügte hinzu, dass der Expander in ist, dann können Sie die ToggleButton zugreifen und die TabIndex im Expander.Loaded Ereignis festgelegt, wie folgt aus:

<Expander x:Name="uiExpander"
          Header="_abc"
          Loaded="uiExpander_Loaded"
          TabIndex="20"
          IsTabStop="False">
    <TextBox TabIndex="30">

    </TextBox>
</Expander>


private void uiExpander_Loaded(object sender, RoutedEventArgs e)
{
    //Gets the HeaderSite part of the default ControlTemplate for an Expander.
    var header = uiExpander.Template.FindName("HeaderSite", uiExpander) as Control;
    if (header != null)
    {
        header.TabIndex = uiExpander.TabIndex;
    }
}

Sie können auch werfen einfach das Senderobjekt zu einem Expander auch, wenn Sie sie brauchen mit mehreren Expandern zu arbeiten. Die andere Option ist Ihre eigene Control für den Expander (n) zu erstellen und sie in dort.

Bearbeiten Wir können auch den Codeabschnitt zu einem AttachedProperty bewegen, so dass es viel sauberer und einfacher zu bedienen:

<Expander local:ExpanderHelper.HeaderTabIndex="20">
    ...
</Expander>

Und die AttachedProperty:

public class ExpanderHelper
{
    public static int GetHeaderTabIndex(DependencyObject obj)
    {
        return (int)obj.GetValue(HeaderTabIndexProperty);
    }

    public static void SetHeaderTabIndex(DependencyObject obj, int value)
    {
        obj.SetValue(HeaderTabIndexProperty, value);
    }

    // Using a DependencyProperty as the backing store for HeaderTabIndex.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeaderTabIndexProperty =
        DependencyProperty.RegisterAttached(
        "HeaderTabIndex",
        typeof(int),
        typeof(ExpanderHelper),
        new FrameworkPropertyMetadata(
            int.MaxValue,
            FrameworkPropertyMetadataOptions.None,
            new PropertyChangedCallback(OnHeaderTabIndexChanged)));

    private static void OnHeaderTabIndexChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var expander = o as Expander;
        int index;

        if (expander != null && int.TryParse(e.NewValue.ToString(), out index))
        {
            if (expander.IsLoaded)
            {
                SetTabIndex(expander, (int)e.NewValue);
            }
            else
            {
                // If the Expander is not yet loaded, then the Header will not be costructed
                // To avoid getting a null refrence to the HeaderSite control part we
                // can delay the setting of the HeaderTabIndex untill after the Expander is loaded.
                expander.Loaded += new RoutedEventHandler((i, j) => SetTabIndex(expander, (int)e.NewValue));
            }
        }
        else
        {
            throw new InvalidCastException();
        }
    }

    private static void SetTabIndex(Expander expander, int index)
    {
        //Gets the HeaderSite part of the default ControlTemplate for an Expander.
        var header = expander.Template.FindName("HeaderSite", expander) as Control;
        if (header != null)
        {
            header.TabIndex = index;
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top