1

新しいビューが読み込まれるときに、特定のテキストボックスに焦点を合わせる必要があります。

解決策は、このコード行をビューのOnLoadedイベントに追加することでした。

Dispatcher.BeginInvoke(() => { NameTextBox.Focus(); });

したがって、これは1つのビューでは機能しましたが、別のビューでは機能しませんでした。問題のデバッグに時間を費やし、OnLoadedイベントの後にBusyIndi​​catorがtrueおよびfalseに設定されていたため、作業中の新しいビューにすべてのコントロールからフォーカスを奪うBusyIndi​​catorがあることに気付きました。

したがって、解決策は、BusyIndi​​catorがfalseに設定されたNameTextBox 後にフォーカスを呼び出すことです。私のアイデアは、この余分な作業を処理する再利用可能なBusyIndi​​catorコントロールを作成することでした。ただし、MVVMでこれを行うのに問題があります。

私はツールキットの単純な拡張を作成することから始めました:BusyIndi​​cator:

public class EnhancedBusyIndicator : BusyIndicator
{
    public UserControl ControlToFocusOn { get; set; }

    private bool _remoteFocusIsEnabled = false;
    public bool RemoteFocusIsEnabled
    {
        get
        {
            return _remoteFocusIsEnabled;
        }
        set
        {
            if (value == true)
                EnableRemoteFocus();
        }
    }

    private void EnableRemoteFocus()
    {
        if (ControlToFocusOn.IsNotNull())
            Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
        else
            throw new InvalidOperationException("ControlToFocusOn has not been set.");
    }

XAMLファイルにコントロールを問題なく追加しました。

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
    IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>    
...
    <my:myTextBox (this extends TextBox)
        x:Name="NameTextBox"
    ...
    />
...
</my:EnhancedBusyIndicator>

つまり、IsRemoteFocusEnabledViewModelでがtrueに設定されている場合(ViewModelでIsBusyfalseに設定した後に実行します)、フォーカスはに設定されNameTextBoxます。そして、それが機能する場合、他の人はを使用EnhancedBusyIndicatorして別のコントロールにバインドし、自分のビューに最初のアクティブがあると仮定して、自分のViewModelでフォーカスを適切に有効にすることができますBusyIndicator

ただし、ビューがロードされると、次の例外が発生します。

プロパティ'foo.Controls.EnhancedBusyIndi​​cator.ControlToFocusOn'を設定すると例外がスローされました。[行:45位置:26]

私が試みているこの解決策は機能しますか?もしそうなら、私がこれまでに持っているものの何が問題になっていますか(ControlToFocusOnプロパティを設定できません)?


アップデート1

Visual Studio 10 Tools for Silverlight 5をインストールしましたが、新しいビューに移動すると、より適切なエラーメッセージが表示されます。今、私はこのエラーメッセージを受け取ります:

「System.ArgumentException:タイプSystem.Windows.Data.BindingのオブジェクトをタイプSystem.Windows.Controls.UserControlに変換できません」

また、このコントロールのDataContextを変更する必要があると思います。コードビハインドコンストラクターでは、DataContextがViewModelに設定されています。DataContextプロパティをに追加しようとしましたEnhancedBusyIndicatorが、機能しませんでした。

<my:EnhancedBusyIndicator
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
    IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>

アップデート2

オブジェクト(を実装する)にフォーカスを設定したいので、に変更UserControlする必要があります。ただし、これで問題が解決するわけではありません。ControlTextBoxControl

4

2 に答える 2

0

ビューに存在しないBusyIndicator場合、フォーカスの問題を解決するための一般的な解決策は、コードを追加することです

Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });

ビューのLoadedイベントに。これは実際にはBusyIndicator現在でも機能します。ただし、BusyIndicatorすぐに残りのSilverlightコントロールからフォーカスが外れます。解決策は、がビジーでないFocus()後にコントロールのメソッドを呼び出すことです。BusyIndicator

私はこのようなコントロールを作ることでそれを解決することができました:

public class EnhancedBusyIndicator : BusyIndicator
{
    public EnhancedBusyIndicator()
    {
        Loaded += new RoutedEventHandler(EnhancedBusyIndicator_Loaded);
    }

    void EnhancedBusyIndicator_Loaded(object sender, RoutedEventArgs e)
    {
        AllowedToFocus = true;
    }

    private readonly DependencyProperty AllowedToFocusProperty = DependencyProperty.Register("AllowedToFocus", typeof(bool), typeof(EnhancedBusyIndicator), new PropertyMetadata(true));

    public bool AllowedToFocus
    {
        get { return (bool)GetValue(AllowedToFocusProperty); }
        set { SetValue(AllowedToFocusProperty, value); }
    }

    public readonly DependencyProperty ControlToFocusOnProperty = DependencyProperty.Register("ControlToFocusOn", typeof(Control), typeof(EnhancedBusyIndicator), null);

    public Control ControlToFocusOn
    {
        get { return (Control)GetValue(ControlToFocusOnProperty); }
        set { SetValue(ControlToFocusOnProperty, value); }
    }

    protected override void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnIsBusyChanged(e);
        if (AllowedToFocus && !IsBusy)
        {
            Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
            AllowedToFocus = false;
        }
    }
}

これを使用するにはBusyIndicator、xamlのタグを新しいものに置き換えEnhancedBusyIndicator、適切な名前空間を追加します。

要素内に新しいプロパティを追加し、消えControlToFocusOnた後にフォーカスしたいビューの既存の要素にバインドします。EnhancedBusyIndicator

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    ...
>
    ...
</my:EnhancedBusyIndicator>

この場合、私は。というテキストボックスに焦点を合わせましたNameTextBox

それでおしまい。このコントロールは、ページに移動するたびにフォーカスを取得します。ページを表示しているときに、EnhancedBusyIndicator忙しくなり、忙しくない場合、フォーカスはコントロールに移動しません。これは初期ロード時にのみ発生します。

EnhancedBusyIndicator別の時間にフォーカスできるようにする場合はControlToFocusOn、別のプロパティを追加しますAllowedToFocus

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    AllowedToFocus="{Binding IsAllowedToFocus}"
    ...
>
    ...
</my:EnhancedBusyIndicator>

がtrueに設定されている場合AllowedToFocus、次にEnhancedBusyIndicatorビジーから非ビジーに切り替わると、フォーカスはに移動しControlToFocusOnます。

AllowedToFocusは、ビューをロードするときにfalseに設定して、フォーカスがコントロールに移動しないようにすることもできます。ViewModelプロパティにバインドする場合はAllowedToFocus、を変更する必要がある場合がありますBindingMode。デフォルトではですOneTime

于 2012-01-18T22:24:53.013 に答える
0

@マット、わからない

DataContext="{Binding RelativeSource={RelativeSource Self}}"

Silverlight 5で動作しますが、静的リソースとしてバインドしてみましたか?

于 2012-01-13T23:11:29.060 に答える