【问题标题】:Get focus back to the control when using INotifyDataErrorInfo for validation使用 INotifyDataErrorInfo 进行验证时将焦点重新返回到控件
【发布时间】:2012-08-21 22:16:05
【问题描述】:

我正在使用 Silverlight 中的 INotifyDataErrorInfo 实现进行简单验证。

提交时,我正在验证所有属性以显示所有错误。

当验证发生时,我需要将焦点返回到出现验证错误的第一个控件。

我们有办法做到这一点吗?有什么建议吗?

【问题讨论】:

    标签: silverlight validation silverlight-4.0 inotifydataerrorinfo


    【解决方案1】:

    迟到总比没有好:)

    我已经实现了这个行为。

    首先,您需要订阅您的 ViewModel ErrorsChangedPropertyChanged 方法。我在我的构造函数中这样做:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      相关资源
      最近更新 更多