Frage

Gibt es eine Möglichkeit Focus von einem Steuerelement zu einem anderen zu setzen mit WPF Triggers?

Wie das folgende Beispiel:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid>  
    <Grid.RowDefinitions>
      <RowDefinition/>
      <RowDefinition/>
      <RowDefinition/>
    </Grid.RowDefinitions>

    <TextBox Name="txtName"></TextBox>    
    <TextBox Grid.Row="1" Name="txtAddress"></TextBox>
    <Button Grid.Row="2" Content="Finish">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">

                <!-- Insert cool code here-->  

            </EventTrigger>
        </Button.Triggers>
    </Button>
  </Grid>
</Page>

Gibt es eine Möglichkeit für diese EventTrigger auf der Textbox „txtName“ konzentrieren zu setzen?

Ich versuche, den Weg zu finden, so etwas wie dies mit strengen MVVM zu tun. Ist dies etwas, das nicht über das XAML (in MVVM) getan werden soll, dann ist das in Ordnung. Aber ich mag eine Art von Dokumentation, um zu sehen, wie sie passte in dem MVVM Muster außerhalb des XAML zu tun.

War es hilfreich?

Lösung

Haben Sie darüber nachgedacht, ein angeschlossenes Verhalten verwenden. Sie sind einfach zu implementieren und AttachedProperty der Verwendung. Obwohl es immer noch Code erfordert, wird dieser Code in einer Klasse abstrahiert und wiederverwendet werden. Sie können die Notwendigkeit, ‚Code hinter‘ beseitigen und werden häufig mit dem MVVM Muster verwendet.

versuchen diese und sehen, ob es für Sie arbeitet.

public class EventFocusAttachment
{
    public static Control GetElementToFocus(Button button)
    {
        return (Control)button.GetValue(ElementToFocusProperty);
    }

    public static void SetElementToFocus(Button button, Control value)
    {
        button.SetValue(ElementToFocusProperty, value);
    }

    public static readonly DependencyProperty ElementToFocusProperty =
        DependencyProperty.RegisterAttached("ElementToFocus", typeof(Control), 
        typeof(EventFocusAttachment), new UIPropertyMetadata(null, ElementToFocusPropertyChanged));

    public static void ElementToFocusPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var button = sender as Button;
        if (button != null)
        {
            button.Click += (s, args) =>
                {
                    Control control = GetElementToFocus(button);
                    if (control != null)
                    {
                        control.Focus();
                    }
                };
        }
    }
}

Und dann in XAML tut so etwas wie ...

<Button 
    Content="Click Me!" 
    local:EventFocusAttachment.ElementToFocus="{Binding ElementName=textBox}" 
    />
<TextBox x:Name="textBox" />

Andere Tipps

Ich bin nicht in der Nähe von Visual Studio, so kann ich nicht wirklich dieses Recht versuche jetzt, aber aus der Spitze von meinem Kopf, sollten Sie in der Lage sein, so etwas zu tun:

FocusManager.FocusedElement="{Binding ElementName=txtName}">

Edit:

Es ist ein Followup Frage (fragte jüngerer Zeit) dazu hier: Wie Autofokus nur in xAML festlegen? , die diese Methode enthält, und ein paar andere Ideen, wie es zu benutzen.

Sie können auch ein WPF-Verhalten verwenden ...

    public class FocusElementAfterClickBehavior : Behavior<ButtonBase>
{
    private ButtonBase _AssociatedButton;

    protected override void OnAttached()
    {
        _AssociatedButton = AssociatedObject;

        _AssociatedButton.Click += AssociatedButtonClick;
    }

    protected override void OnDetaching()
    {
        _AssociatedButton.Click -= AssociatedButtonClick;
    }

    void AssociatedButtonClick(object sender, RoutedEventArgs e)
    {
        Keyboard.Focus(FocusElement);
    }

    public Control FocusElement
    {
        get { return (Control)GetValue(FocusElementProperty); }
        set { SetValue(FocusElementProperty, value); }
    }

    // Using a DependencyProperty as the backing store for FocusElement.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FocusElementProperty =
        DependencyProperty.Register("FocusElement", typeof(Control), typeof(FocusElementAfterClickBehavior), new UIPropertyMetadata());
}

Hier ist das XAML, das Verhalten zu verwenden.

Namespaces enthalten:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:local="clr-namespace:WpfApplication1"

Anhängen WPF Verhalten auf Schaltfläche und binden Element Sie Fokus einstellen möchten:

<Button Content="Focus" Width="75">
    <i:Interaction.Behaviors>
        <local:FocusElementAfterClickBehavior FocusElement="{Binding ElementName=CheckBoxComboBox, Mode=OneWay}"/>
    </i:Interaction.Behaviors>
</Button>
<ComboBox x:Name="CheckBoxComboBox" HorizontalAlignment="Center" VerticalAlignment="Center" Width="120" Grid.Row="1"/>

So diese Weise haben Sie keinen Code hinter und es ist wiederverwendbar auf jeder Kontrolle, die von Button erbt.

Hoffe, das hilft jemand.

Sie benötigen einen TriggerAction den Focus () -Methode auf die gewünschte Steuerung aufzurufen.

public class SetFocusTrigger : TargetedTriggerAction<Control>
{
 protected override void Invoke(object parameter)
 {
    if (Target == null) return;

    Target.Focus();
 }
}

den Fokus haben, auf eine Kontrolle setzen, legen Sie eine Trigger Sammlung nach dem LayoutRoot (oder jede Kontrolle wirklich), wählen Sie das Ereignis als Auslöser, und wählen Sie die SetFocusTrigger wie die Klasse zu laufen. In der SetFocusTrigger Erklärung, setzen Sie den Namen der Steuerung, die Sie den Fokus mithilfe der Targetname-Eigenschaft erhalten möchten.

<Button x:Name="LayoutRoot" >
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Clicked">
        <local:SetFocusTrigger TargetName="StartHere"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

<TextBox x:Name="StartHere"/>
</Button>

Ist das, was Sie wollen?

    <TextBox Name="txtName"></TextBox>
    <TextBox Grid.Row="1" Name="txtAddress"></TextBox>
    <Button Grid.Row="2" Content="Finish">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <EventSetter Event="Click" Handler="MoveFocusOnClick" />
            </Style>
        </Button.Style>
        <!--<Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
            </EventTrigger>
        </Button.Triggers>-->
    </Button>

c #:

    public void MoveFocusOnClick(object sender, RoutedEventArgs e)
    {
        Keyboard.Focus(txtName); // Or your own logic
    }

Dies ist das gleiche wie Ian Oakes' Lösung, aber ich habe ein paar kleinere Änderungen.

  1. Die Schaltfläche Typ allgemeiner sein kann, nämlich ButtonBase mehr Fälle, wie ToggleButton zu behandeln.
  2. Der Typ Ziel kann auch allgemeinere, nämlich UIElement sein. Technisch gesehen, könnte dies IInputElement, nehme ich an.
  3. Made der Event-Handler statisch, so dass es nicht eine Laufzeit Schließung jedes Mal erzeugen wird diese verwendet wird.
  4. [edit: 2019]. Aktualisiert null-bedingte zu verwenden und C # 7 Ausdruck Körper Syntax

Vielen Dank an Ian.


public sealed class EventFocusAttachment
{
    public static UIElement GetTarget(ButtonBase b) => (UIElement)b.GetValue(TargetProperty);

    public static void SetTarget(ButtonBase b, UIElement tgt) => b.SetValue(TargetProperty, tgt);

    public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
            "Target",
            typeof(UIElement),
            typeof(EventFocusAttachment),
            new UIPropertyMetadata(null, (b, _) => (b as ButtonBase)?.AddHandler(
                ButtonBase.ClickEvent,
                new RoutedEventHandler((bb, __) => GetTarget((ButtonBase)bb)?.Focus()))));
};

Die Verwendung ist grundsätzlich die gleiche wie oben:

<ToggleButton z:EventFocusAttachment.Target="{Binding RelativeSource={RelativeSource Self}}" />

Beachten Sie, dass die Veranstaltung ausrichten können / fokussieren den Ursprung Schaltfläche selbst.

Sehen Sie, wenn Sie irgendeine Dispatcher verwenden, dann wäre es hilfreich sein, aber dies ist nur ein kurzer Trick, den ich in meinem Code verwendet. Verwenden Sie einfach das Loaded-Ereignis in Ihrem XAML und einen neuen Handler machen. In diesem Handler diesen Code und Bingo einfügen! sind bereit, Sie gehen

Ihre geladene Veranstaltung mit einigen Argumenten hier ...

{
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, new System.Action(() => {
        The element to be focused goes here......
    }));
}

PS: Es erfordert Windows. Threading, wenn Sie nicht wissen;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top