1

SilverlightでINotifyDataErrorInfoの実装を使用して簡単な検証を使用しています。検証のためにINotifyDataErrorInfoを使用するときにコントロールにフォーカスを戻す

私はすべてのエラーを表示するためにすべてのプロパティを検証しています。

妥当性検査が行われるときに、検証エラーで最初のコントロールにフォーカスを戻す必要があります。

これを行う方法はありますか?助言がありますか?

答えて

0

私はこれを実装しました。

まず、ViewModel ErrorsChangedおよびPropertyChangedメソッドを購読する必要があります。私は、コンストラクタでこれをやっている:

/// <summary> 
    /// Initializes new instance of the View class. 
    /// </summary> 
    public View(ViewModel viewModel) 
    { 
     if (viewModel == null) 
      throw new ArgumentNullException("viewModel"); 

     // Initialize the control 
     InitializeComponent(); // exception 

     // Set view model to data context. 
     DataContext = viewModel; 

     viewModel.PropertyChanged += new PropertyChangedEventHandler(_ViewModelPropertyChanged); 
     viewModel.ErrorsChanged += new EventHandler<DataErrorsChangedEventArgs>(_ViewModelErrorsChanged); 
    } 

次に、このイベントのハンドラを記述します。

/// <summary> 
    /// If model errors has changed and model still have errors set flag to true, 
    /// if we dont have errors - set flag to false. 
    /// </summary> 
    /// <param name="sender">Ignored.</param> 
    /// <param name="e">Ignored.</param> 
    private void _ViewModelErrorsChanged(object sender, DataErrorsChangedEventArgs e) 
    { 
     if ((this.DataContext as INotifyDataErrorInfo).HasErrors) 
      _hasErrorsRecentlyChanged = true; 
     else 
      _hasErrorsRecentlyChanged = false; 
    } 

    /// <summary> 
    /// Iterate over view model visual childrens. 
    /// </summary> 
    /// <param name="sender">Ignored.</param> 
    /// <param name="e">Ignored.</param> 
    private void _ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if ((this.DataContext as INotifyDataErrorInfo).HasErrors) 
      _LoopThroughControls(this); 
    } 

そして最後にメソッドを追加します。

/// <summary> 
    /// If we have error and we haven't already set focus - set focus to first control with error. 
    /// </summary> 
    /// <remarks>Recursive.</remarks> 
    /// <param name="parent">Parent element.</param> 
    private void _LoopThroughControls(UIElement parent) 
    { 
     // Check that we have error and we haven't already set focus 
     if (!_hasErrorsRecentlyChanged) 
      return; 

     int count = VisualTreeHelper.GetChildrenCount(parent); 

     // VisualTreeHelper.GetChildrenCount for TabControl will always return 0, so we need to 
     // do this branch of code. 
     if (parent.GetType().Equals(typeof(TabControl))) 
     { 
      TabControl tabContainer = ((TabControl)parent); 
      foreach (TabItem tabItem in tabContainer.Items) 
      { 
       if (tabItem.Content == null) 
        continue; 

       _LoopThroughControls(tabItem.Content as UIElement); 
      } 
     } 

     // If element has childs. 
     if (count > 0) 
     { 
      for (int i = 0; i < count; i++) 
      { 
       UIElement child = (UIElement)VisualTreeHelper.GetChild(parent, i); 

       if (child is System.Windows.Controls.Control) 
       { 
        var control = (System.Windows.Controls.Control)child; 

        // If control have error - we found first control, set focus to it and 
        // set flag to false. 
        if ((bool)control.GetValue(Validation.HasErrorProperty)) 
        { 
         _hasErrorsRecentlyChanged = false; 
         control.Focus(); 
         return; 
        } 
       } 

       _LoopThroughControls(child); 
      } 
     } 
    } 
関連する問題