2012-01-13 15 views
1

新しいビューが読み込まれたときに特定のテキストボックスにフォーカスする必要があります。UserControlをカスタムBusyIndi​​catorコントロールにバインドする

ソリューションは、ビューのOnLoadedイベントにこのコード行を追加しました:

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

は、これは一つのビューのために働いていたではなく、別の。私は問題をデバッグするのに少し時間を費やし、BusyIndi​​catorがOnLoadedイベントの後にtrueおよびfalseに設定されているので、すべてのコントロールからフォーカスを外すBusyIndi​​catorが、新しいビューで使用されていることに気付きました。

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

私は、ツールキットの単純な拡張することによって開始:私は何の問題もなく私のXAMLファイルにコントロールを追加

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."); 
    } 

:BusyIndi​​catorを

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

IsRemoteFocusEnabledがあるときにアイデアがありますViewModelでtrueに設定されています(これはViewModelでIsBusyをfalseに設定した後に行います)、フォーカスはNameTextBoxに設定されます。それがうまくいけば、他の人がEnhancedBusyIndicatorを使用し、別のコントロールにバインドして、自分のViewModels内で適切にフォーカスを有効にできます。ビューの初期値はBusyIndicatorです。ビューがロードされたときに

はしかし、私はこの例外を取得:プロパティ「foo.Controls.EnhancedBusyIndi​​cator.ControlToFocusOn」

設定が例外をスローしました。 [行:45位置:26]

私はこのソリューションを試していますか?もしそうなら、私がこれまでに持っていたもので何が間違っていますか(ControlToFocusOnプロパティを設定できません)?


アップデート1

私は、Visual StudioにSilverlightの5のための10個のツールをインストールし、新しいビューにナビゲートするときに、より良いエラーメッセージが表示されました。今、私はこのエラーメッセージをGeteの:

:また

を「System.ArgumentExceptionのタイプSystem.Windows.Data.BindingのオブジェクトがSystem.Windows.Controls.UserControl型に変換することができない」、私は私がする必要があると思いますこのコントロールのDataContextを変更します。コードビハインドコンストラクタでは、DataContextがMy ViewModelに設定されます。私はEnhancedBusyIndicatorにDataContextプロパティを追加しようとしたが、それはうまくいきませんでした:

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

アップデート2

私はにフォーカスを設定したいされますので、私はControlUserControlを変更する必要がありますTextBoxオブジェクト(Controlを実装しています)。しかし、これでは問題は解決しません。

答えて

0

ビューにBusyIndicator存在しないと、フォーカスの問題を解決するための一般的な解決策は、ビューのLoadedイベントにコード

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

を追加することです。これは実際にBusyIndicatorが存在する場合でも機能します。ただし、BusyIndicatorはすぐに残りのSilverlightコントロールからフォーカスを離します。その解決策は、BusyIndicatorではなく、がビジーである後に、Focus()コントロールのメソッドを呼び出すことです。

私はこのような制御を行うことによってそれを解決することができました:

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

、それを使用する新しいEnhancedBusyIndicatorであなたのXAMLでBusyIndicatorタグを交換し、適切な名前空間を追加します。

、要素内部ControlToFocusOnを新しいプロパティを追加し、EnhancedBusyIndicatorが消えた後、あなたが上にあるように焦点を当てたいビュー内の既存の要素にバインド:この場合

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

を、私はに焦点を当てましたNameTextBoxというテキストボックス。

これだけです。このコントロールは、ページに移動するたびにフォーカスを取得します。我々がページ上にある間に、EnhancedBusyIndicatorがビジー状態でビジー状態でなければ、フォーカスはコントロールに行きません。これは最初の負荷でのみ発生します。

はあなたがAllowedToFocusEnhancedBusyIndicatorは、ControlToFocusOnに別の時間を集中する別のプロパティを追加できるようにしたい場合:

AllowedToFocusがtrueに設定されている
<my:EnhancedBusyIndicator 
    ControlToFocusOn="{Binding ElementName=NameTextBox}" 
    AllowedToFocus="{Binding IsAllowedToFocus}" 
    ... 
> 
    ... 
</my:EnhancedBusyIndicator> 

、次回ビジーでないと忙しいからEnhancedBusyIndicatorスイッチ、フォーカスはControlToFocusOnになります。

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

0

@Matt、

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

わからないあなたは、静的リソースとしてそれを結合しようとしている、シルバー5で動作しますか?

+0

私は実際にSilverlight 4を使用しています。 Silverlight 4用にVisual Studio 10 Tools for Silverlight 5を使用して「Update 1」に投稿したより良いエラーメッセージを取得できました。私は静的リソースとしてバインドしようとしていません。私はそれを試してみましょう。 –

関連する問題