【问题标题】:Button binding to Validation按钮绑定到验证
【发布时间】:2015-08-07 15:41:14
【问题描述】:

所以我有一个“保存”按钮,如果有任何验证错误,我想禁用它,如果错误消失,我想启用它。我有一个 BindingGroup,想知道是否可以将 IsEnabled 绑定到 BindingGroup Validation.HasError(但布尔值相反)。

这是我为 xaml 设置的设置

<telerik:RadWindow x:Class="Outreach_Application_1.MVVM.ContactPopup"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             Header="Contact Details"
             mc:Ignorable="d" Style="{DynamicResource ContactWindowDictionary}">
    <StackPanel>
        <StackPanel.BindingGroup>
            <BindingGroup Name="ContactGroup" />
        </StackPanel.BindingGroup>
        <Border Width="Auto" Height="25" Background="{StaticResource DhpBlueBrush}">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" 
                       Foreground="White" FontWeight="Bold" FontSize="12" 
                       Text="{Binding ContactWindowHeader}"/>
        </Border>
        <DockPanel>
            <StackPanel Margin="4">
                <Label Content="Title" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="First" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="MI" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Last" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Position" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Email" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Phone" FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Phone Ext." FontWeight="Bold" HorizontalContentAlignment="Right"/>
                <Label Content="Fax" FontWeight="Bold" HorizontalContentAlignment="Right"/>
            </StackPanel>
            <StackPanel Margin="4" Width="400">
                <!-- Title -->
                <ComboBox Width="50" Margin="2" HorizontalAlignment="Left"
                            SelectedValue="{Binding Path=Title, 
                                                    Mode=TwoWay}"
                            ItemsSource="{Binding Path=TitleSource, 
                                                Mode=TwoWay}" />
                <!-- First Name -->
                <telerik:RadMaskedTextInput Margin="2" Width="125"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            AllowInvalidValues="True"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=FirstName, 
                                                            Mode=TwoWay,
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />
                <!-- Middle Initial -->
                <telerik:RadMaskedTextInput Margin="2" Width="30"
                                            AllowInvalidValues="True"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=MiddleInitial, 
                                                            Mode=TwoWay, 
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />
                <!-- Last Name -->
                <telerik:RadMaskedTextInput Margin="2" Width="125"
                                            AllowInvalidValues="True"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=LastName, 
                                                            Mode=TwoWay,  
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />

                <!-- Position -->
                <telerik:RadMaskedTextInput Margin="2" Width="125"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=Position, 
                                                            Mode=TwoWay}" />
                <!-- Email -->
                <telerik:RadMaskedTextInput Margin="2" Width="125"
                                            AllowInvalidValues="True"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=Email, 
                                                            Mode=TwoWay,  
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />
                <!-- Phone Number -->
                <telerik:RadMaskedTextInput Margin="2" Width="100"
                                            AllowInvalidValues="True"
                                            IsClearButtonVisible="False"
                                            Mask="(ddd) ddd-dddd"
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=PhoneNumber, 
                                                            Mode=TwoWay, 
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />
                <!-- Phone Extension -->
                <telerik:RadMaskedTextInput Margin="2" Width="50"
                                            IsClearButtonVisible="False"
                                            Mask=""
                                            SelectionOnFocus="Unchanged"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=PhoneExtension, 
                                                        Mode=TwoWay,  
                                                        ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                        UpdateSourceTrigger=PropertyChanged}" />
                <!-- Fax Number -->
                <telerik:RadMaskedTextInput Margin="2" Width="100"
                                            AllowInvalidValues="True"
                                            IsClearButtonVisible="False"
                                            Mask="(ddd) ddd-dddd"
                                            SelectionOnFocus="Unchanged"
                                            TextMode="PlainText"
                                            Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"
                                            Value="{Binding Path=FaxNumber, 
                                                            Mode=TwoWay, 
                                                            ValidatesOnDataErrors=True,
                                                            BindingGroupName=ContactGroup,
                                                            UpdateSourceTrigger=PropertyChanged}" />
            </StackPanel>

        </DockPanel>
        <Border BorderBrush="Black" BorderThickness="0,0,0,1" Margin="0 6" />
        <DockPanel HorizontalAlignment="Center">
            <Button Content="Cancel" Width="50" FontWeight="Bold" Margin="16 4" 
                    Click="CancelContact_OnClick"/>
            <Button Content="Save" Width="50" FontWeight="Bold" Margin="16 4" 
                    Click="SaveContact_OnClick"
                    IsEnabled="{Binding BindingGroupName=ContactGroup, Path=(Validation.Errors)}">
            </Button>
        </DockPanel>
    </StackPanel>
</telerik:RadWindow>

更新:这是我正在使用的 ViewModel 方面

public class Contact : ViewModelBase, IDataErrorInfo, INotifyPropertyChanged
{
    private string _email;
    private string _faxNumber;
    private string _firstName;
    private string _lastName;
    private string _middleInitial;
    private string _phoneExtension;
    private string _phoneNumber;
    private string _position;
    private string _error = string.Empty;

    //Declare contact variables
    private string _title;
    private bool _canSave;

    //Title
    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged("Title");
        }
    }

    //First Name
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    //MiddleInitial
    public string MiddleInitial
    {
        get { return _middleInitial; }
        set
        {
            _middleInitial = value;
            OnPropertyChanged("MiddleInitial");
        }
    }

    //Last Name
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged("LastName");
        }
    }

    //Position
    public string Position
    {
        get { return _position; }
        set
        {
            _position = value;
            OnPropertyChanged("Position");
        }
    }

    //Email
    public string Email
    {
        get { return _email; }
        set
        {
            _email = value;
            OnPropertyChanged("Email");
        }
    }

    //Phone Number
    public string PhoneNumber
    {
        get { return _phoneNumber; }
        set
        {
            _phoneNumber = value;
            OnPropertyChanged("PhoneNumber");
        }
    }

    //Phone Extension
    public string PhoneExtension
    {
        get { return _phoneExtension; }
        set
        {
            _phoneExtension = value;
            OnPropertyChanged("PhoneExtension");
        }
    }

    //Fax Number
    public string FaxNumber
    {
        get { return _faxNumber; }
        set
        {
            _faxNumber = value;
            OnPropertyChanged("FaxNumber");
        }
    }

    public bool CanSave
    {
        get { return this._canSave; }
        set
        {
            this._canSave = value;
            base.OnPropertyChanged("CanSave");
        }
    }

    #region IDataErrorInfo Members
    public string Error
    {
        get { return _error; }
    }

    public string this[string columnName]
    {
        get
        {
            _error = string.Empty;

            string pattern;

            //First name Validation
            pattern = @"\b^[A-Za-z][a-zA-Z '&-]*[A-Za-z]*$\b";
            if (columnName == "FirstName" && Regex.IsMatch(FirstName, pattern) == false)
            {
                _error = "Invalid first name.";
                CanSave = false;
            }

            if (columnName == "FirstName" && string.IsNullOrWhiteSpace(FirstName))
            {
                _error = "First name is required.";
                CanSave = false;
            }

            //Middle Initial Validation
            pattern = @"(^$)|\b^[A-Za-z]$\b";
            if (columnName == "MiddleInitial" && Regex.IsMatch(MiddleInitial, pattern) == false)
            {
                _error = "Invalid middle initial.";
                CanSave = false;
            }

            //Last name validation
            pattern = @"\b^[A-Za-z][a-zA-Z '&-]*[A-Za-z]*$\b";
            if (columnName == "LastName" && Regex.IsMatch(LastName, pattern) == false)
            {
                _error = "Invalid last name.";
                CanSave = false;
            }

            if (columnName == "LastName" && string.IsNullOrWhiteSpace(LastName))
            {
                _error = "Last name is required.";
                CanSave = false;
            }

            //Email validation
            pattern =
                @"^(?("")("".+?(?<!\\)""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9A-Za-z])@))" +
                @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]*\.)+[A-Za-z0-9][\-A-Za-z0-9]{0,22}[A-Za-z0-9]))$";
            if (columnName == "Email" && Regex.IsMatch(Email, pattern) == false)
            {
                _error = @"Please enter a valid email address.";
                CanSave = false;
            }

            if (columnName == "Email" && string.IsNullOrWhiteSpace(Email))
            {
                _error = @"Email address is required.";
                CanSave = false;
            }

            //Phone number validation
            pattern = @"^[0-9]{10}$";
            if (columnName == "PhoneNumber" && Regex.IsMatch(PhoneNumber, pattern) == false)
            {
                _error = "Please enter a 10 digit phone number.";
                CanSave = false;
            }

            if (columnName == "PhoneNumber" && string.IsNullOrWhiteSpace(PhoneNumber))
            {
                _error = "A phone number is required.";
                CanSave = false;
            }

            //Phone extension validation
            pattern = @"^(^$)|[0-9]+$";
            if (columnName == "PhoneExtension" && Regex.IsMatch(PhoneExtension, pattern) == false)
            {
                _error = "Only numerical digits are allowed.";
                CanSave = false;
            }

            //Fax number validation
            pattern = @"^[0-9]{10}$";
            if (columnName == "FaxNumber" && Regex.IsMatch(FaxNumber, pattern) == false)
            {
                _error = "Please enter a 10 digit fax number.";
                CanSave = false;
            }

            if (columnName == "FaxNumber" && string.IsNullOrWhiteSpace(FaxNumber))
            {
                _error = "A fax number is required.";
                CanSave = false;
            }

            return _error;
        }
    }

    #endregion
}

我试图将保存按钮绑定到 CanSave,但只要一个对象有效,它就会启用该按钮。我想赞扬这一行动。一旦一个对象无效,按钮就会被禁用。

【问题讨论】:

  • 绑定组在其DataContext中的对象是什么?
  • @OmegaMan 它是顶部的 StackPanel。数据 contaxt 被添加到 RadWindow 本身。

标签: wpf validation binding


【解决方案1】:

其实很简单,

XAML

   <Button Content="Save" Width="50" FontWeight="Bold" Margin="16 4" 
                        Click="SaveContact_OnClick"
                        IsEnabled="{Binding Path=IsValid}">

Model.cs

...  
...  
//Below Code to check if the model is Valid (without errors)
public bool IsValid
{
     get
     {
          return (Validation.Errors.Count == 0);
     }
}

//Also you might need to add the below line in your property changed 
   protected virtual void OnPropertyChanged(string propertyName)
        {   
                ...   
                //Below line is needed to fire Notify Property changed   
                this.PropertyChanged(this, new PropertyChangedEventArgs("IsValid"));   
                ...   
        }
...  
...

如果您有任何疑问,请告诉我

【讨论】:

  • 我似乎找不到放置 IsValid 的地方。
  • 将其添加到具有其余属性的类中。 (即头衔、名字等)
  • 它无法识别 Validation.Errors
  • 您的模型类型是什么,是实体模型还是自定义模型。您是如何实施验证的?
【解决方案2】:

将 IsEnabled 绑定到 BindingGroup Validation.HasError(但布尔值相反)。

绑定组更多地是为 Submit / pull 主题设计的,其中按钮始终处于活动状态并开始验证过程。失败会将NotifyOnValidationError 属性设置为true,但这是事后的结果,在这种情况下无济于事。

您寻求的是 push 类型的验证,其中所有验证都可以将任何更改实时推送到变量,该变量可以通过按钮的IsEnabled 绑定。

有关示例,请参见 Validation in Windows Presentation Foundation - CodeProject

【讨论】:

  • 我没有在文档中看到推送发生在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2017-07-30
  • 2011-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-27
相关资源
最近更新 更多