26

FocusWPF を使用して、あるコントロールから別のコントロールに設定する方法はありTriggerますか?

次の例のように:

<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>

EventTriggerこれがテキストボックスの「txtName」に焦点を当てる方法はありますか?

厳密なMVVMを使用して、このようなことを行う方法を見つけようとしています。これが (MVVM の) XAML を介して実行されるべきではない場合は、問題ありません。しかし、XAML の外でそれを行う MVVM パターンにどのように適合するかについて、ある種のドキュメントを見たいと思います。

4

7 に答える 7

35

付属の動作を使用することを検討しましたか。AttachedProperty の実装と使用は簡単です。それでもコードが必要ですが、このコードはクラスで抽象化され、再利用されます。これらは「コード ビハインド」の必要性をなくすことができ、MVVM パターンでよく使用されます。

これを試して、うまくいくかどうかを確認してください。

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();
                    }
                };
        }
    }
}

そして、XAMLで次のようなことを行います...

<Button 
    Content="Click Me!" 
    local:EventFocusAttachment.ElementToFocus="{Binding ElementName=textBox}" 
    />
<TextBox x:Name="textBox" />
于 2010-02-06T11:30:15.287 に答える
17

私はビジュアルスタジオの近くにいないので、今は実際にこれを試すことはできませんが、私の頭の上から、次のようなことができるはずです:

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

編集:

これに関するフォローアップの質問 (最近尋ねられたもの) がここにあります: How to set autofocus only in xaml? このメソッドと、その使用方法に関するいくつかの異なるアイデアが含まれています。

于 2010-02-05T01:00:40.777 に答える
10

WPFの動作を使用することもできます...

    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());
}

動作を使用するXAMLは次のとおりです。

名前空間を含める:

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

WPFビヘイビアをボタンにアタッチし、フォーカスを設定する要素をバインドします。

<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"/>

したがって、この方法ではコードが背後になく、ButtonBaseから継承するすべてのコントロールで再利用できます。

これが誰かを助けることを願っています。

于 2011-03-01T23:42:08.933 に答える
1

これは Ian Oakes のソリューションと同じですが、いくつかの小さな変更を加えました。

  1. ボタンのタイプは、より一般的なものにすることができます。つまりButtonBase、 などのより多くのケースを処理できますToggleButton
  2. ターゲット タイプは、より一般的なもの、つまりUIElement. 技術的には、これは可能性があるIInputElementと思います。
  3. これが使用されるたびにランタイム クロージャーが生成されないように、イベント ハンドラーを静的にしました。
  4. [編集: 2019] null 条件と C#7 式本体の構文を使用するように更新されました。

イアンに感謝します。


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()))));
};

使い方は基本的に上記と同じです。

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

イベントは元のボタン自体をターゲット/フォーカスできることに注意してください。

于 2015-06-12T00:25:39.530 に答える
1

これは、あなたの望むことですか?

    <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
    }
于 2010-02-05T06:26:24.577 に答える