实现 IDataErrorInfo 和数据绑定

Posted

技术标签:

【中文标题】实现 IDataErrorInfo 和数据绑定【英文标题】:Implementing IDataErrorInfo & databinding 【发布时间】:2010-03-11 12:15:20 【问题描述】:

如果我的表单中某些文本框的验证返回 true,我正在尝试更改按钮的 IsEnabled 属性。所以如果有错误,IsEnabled属性应该设置为false。

由于某种原因,我无法让它工作。 IDataErrorInfo 实现仅在调用 IsEmailValid 属性后调用,因此 Validation.GetHasError 始终返回 false,并且我的按钮永远不会被禁用。

有人可以帮忙吗?

代码:

使用 IDataErrorInfo 验证的文本框

<TextBox Style="StaticResource textBoxInError" Name="txtEmail" Grid.Column="1" Grid.Row="2" Width="150" Height="23" HorizontalAlignment="Right" VerticalAlignment="Center">
            <TextBox.Text>
                <Binding Path="Email" Mode="TwoWay"
                         ValidatesOnDataErrors="True"
                         UpdateSourceTrigger="LostFocus"
                         ></Binding>
            </TextBox.Text>
        </TextBox>

IDataErrorInfo 实现:

 public string Error
        
            get
            
                return null;
            
        

        public string this[string name]
        
            get
            
                string result = null;
                #region Email
                if (name == "Email")
                
                    if (!presenter.LenientValidateEmail(Email))
                                          
                         result = "Your email address is not valid";

                    

                
                #endregion

                #region Website

                #endregion
                return result;
            
        

IsEnabled 上的按钮绑定

<Button Name="btnUpdate" IsEnabled="Binding IsValid" HorizontalAlignment="Left" Grid.Column="3" Grid.RowSpan="2" Grid.Row="6" Height="23" Width="75" Click="btnUpdate_Click">Update
        </Button>

public bool IsValid
        
            get
            
                return IsEmailValid();
            
        



public string Email
        
            get
            
                return _email;
            
            set
            
                _email = value;
                OnPropertyChanged("Email"); // executes before IDataErrorInfo Implementation
            
        




 private bool IsEmailValid()
    
        object el = FindName("txtEmail");


        if (el != null)
        
            _isEmailValid = Validation.GetHasError((DependencyObject)el); // always false??

            if (_isEmailValid)
            
                return false;
            
            else
                return true;
        
        return true;

    

//PropertyChanged event handler:
    void ProfileView_PropertyChanged(object sender, PropertyChangedEventArgs e)
            
                IsEmailValid();
            

【问题讨论】:

【参考方案1】:

当我理解您的代码提取正确时,我认为问题在于输入无效电子邮件地址时不会通知 UI。在 ProfileView_PropertyChanged(...) 中,您检查电子邮件是否有效,如果无效,IsEmailValid() 应返回 false。然而,这个结果没有做任何事情。最重要的是:UI 不会收到有关 IsValid 属性更改的通知,因此按钮的 IsEnabled 状态不会更新。当然,在输入无效电子邮件后 IsValid 属性的返回值会发生变化,但 UI 不会请求这个新值。

解决方案应该是在 ProfileView_PropertyChanged(...) 方法中为 IsValid 属性引发 PropertyChanged 事件,如下所示:

void ProfileView_PropertyChanged(object sender, PropertyChangedEventArgs e)

    IsEmailValid();
    OnPropertyChanged("IsValid"); // <== this one is important!

您也可以将 OnPropertyChanged(...) 调用包装到 if 语句中,具体取决于 IsEmailValid() 的结果,但这取决于您。

实际上,您甚至不需要调用其中的 IsEmailValid() 方法,因为它会在 PropertyChanged 事件引发后立即被调用。但是,我不想删除它,因为我不知道这是否会在您的应用程序中引入一些其他错误。

【讨论】:

【参考方案2】:

我已经解决了。

使用字典跟踪由 IDataErrorInfo 生成的所有错误,然后在 IsEmailValid() 中验证电子邮件地址。然后如果电子邮件有效或无效,则从字典中添加/删除错误! :)

【讨论】:

以上是关于实现 IDataErrorInfo 和数据绑定的主要内容,如果未能解决你的问题,请参考以下文章

WP7 Linq To SQL(SQL CE) IDataErrorInfo

WPF使用IDataErrorInfo进行数据校验

WPF使用IDataErrorInfo接口进行数据校验 - 简书

未实现 IDataErrorInfo 并获得验证

在用户将数据输入字段之前如何防止验证?

从其他 Xaml 文件绑定到用户控件中的元素