Steve
Steve

Reputation: 35

Doesn't disable the button if the textbox invalid

I have the email text block with validation

<TextBox x:Name="email" Style="{StaticResource emaliStyle}" Grid.Column="2" Grid.Row="2">
                <TextBox.Text>
                    <Binding  Mode="TwoWay" Path="Email"  UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <DataErrorValidationRule ValidatesOnTargetUpdated="False"/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

 <Style TargetType="TextBox" x:Key="emaliStyle">
        <Setter Property="Width" Value="220"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="Padding" Value="6,1,1,0"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}" 
                            CornerRadius="10"
                            SnapsToDevicePixels="True">
                        <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Setter x:Name="LoginValidation" Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="True">
                        <TextBlock DockPanel.Dock="Bottom" Foreground="Maroon" FontSize="8pt"
                                           Text="{Binding ElementName=email, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                        </TextBlock>
                        <AdornedElementPlaceholder Name="email" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="BorderBrush" Value="DarkRed" />
                <Setter Property="BorderThickness" Value="2" />
            </Trigger>
        </Style.Triggers>
    </Style>

the validation work and show me the message which I write in viewModel( it doesn't matter)

next step it blocks the button if the field is invalid.

my button and style for it

 <Button x:Name="SignInButton" 
                    Style="{StaticResource SignInButton}"
                    Command="{Binding SignInCommand}" 
                    CommandParameter="{Binding ElementName=This}" 
                    Content="Sign In"/>

 <Style TargetType="Button" x:Key="SignInButton">
        <Setter Property="Background" Value="MidnightBlue"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Width" Value="100"/>
        <Setter Property="Height" Value="40"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border Background="{TemplateBinding Background}" CornerRadius="10">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" Margin="26,10"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="IsEnabled" Value="False"/>
        <Style.Triggers >
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=(Validation.HasError), ElementName=email}" Value="False"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="IsEnabled" Value="True"/>
            </MultiDataTrigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="LimeGreen"/>
            </Trigger>

        </Style.Triggers>
    </Style>

I write the Multitrigger(later add other textbox fields) to disable my button, but it isn't work.

I try write all with element name Email doesn't help. What i miss? because the error message will show and the field border mark red, bu isn't disable

Upvotes: 1

Views: 655

Answers (1)

mm8
mm8

Reputation: 169160

Your BlockButton() method should return false whenever you want to disable the Button that is bound to the SignInCommand. There is no reason to set the IsEnabled property in a style when you bind to a command.

For the status of the command and the Button to get refeshed, you should raise the CanExecuteChanged event for the command whenever the validation status changes. Most ICommand implementations include a RaiseCanExecuteChanged() method or similar that lets you do this:

private bool _isEmailValid;

private bool BlockButton()
{
    return _isEmailValid && IsAppDeveloper == false && IsEndUser == false;
}

public string this[string columnName]
{
    get
    {
        string error = String.Empty;
        switch (columnName)
        {
            case "Email":
                string s = ValidateModelProperty(Email, columnName);
                _isEmailValid = string.IsNullOrEmpty(s);
                SignInCommand.RaiseCanExecuteChanged();
                return s;
        }

        return error;
    }
}

private string ValidateModelProperty(object value, string propertyName)
{
    ICollection<ValidationResult> validationResults = new List<ValidationResult>();
    ValidationContext validationContext = new ValidationContext(this, null, null) { MemberName = propertyName };
    if (!Validator.TryValidateProperty(value, validationContext, validationResults))
        foreach (ValidationResult validationResult in validationResults)
            return validationResult.ErrorMessage;
    return null;
}

Upvotes: 1

Related Questions