Mefhisto1
Mefhisto1

Reputation: 2228

Disable a button if either of the two TextBoxes are empty

I have two text boxes and one button. If either of the boxes is empty or white space, the button should be disabled.

<TextBox Name="firstNameTxtBox" />
<TextBox Name="lastNameTxtBox" />

<Button Content="Save" Command="{Binding Save}"  Style="{StaticResource saveButtonEnabler}" />

And the saveButtonEnabler resource:

<UserControl.Resources>
    <converters:IsButtonEnabledConverter x:Key="isButtonEnabledConverter" />
        <Style x:Key="saveButtonEnabler" TargetType="Button">
            <Setter Property="IsEnabled" Value="False"/>
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding ElementName=firstNameTxtBox, Path=Text.Length, Converter={StaticResource isButtonEnabledConverter}}" Value="???" />
                        <Condition Binding="{Binding ElementName=lastNameTxtBox, Path=Text.Length, Converter={StaticResource isButtonEnabledConverter}}" Value="???" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsEnabled" Value="True"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
</UserControl.Resources>

Converter gets called appropriately, but I have not idea how to set the result to the Value of the Condition.

public class IsButtonEnabledConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value == 0 ? false : true;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Upvotes: 9

Views: 16342

Answers (4)

Janne Matikainen
Janne Matikainen

Reputation: 5121

Actually you need to use 2 triggers to set IsEnabled to false. Your current implementation is AND and what you want is OR.

<TextBox x:Name="firstNameTxtBox"/>
<TextBox x:Name="lastNameTxtBox"/>
<Button Content="Save">
  <Button.Style>
     <Style TargetType="{x:Type Button}">
         <Style.Triggers>
             <DataTrigger Binding="{Binding Text.Length, ElementName=firstNameTxtBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
                 <Setter Property="IsEnabled" Value="False"/>
             </DataTrigger>
             <DataTrigger Binding="{Binding Text.Length, ElementName=lastNameTxtBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
                 <Setter Property="IsEnabled" Value="False"/>
             </DataTrigger>
         </Style.Triggers>
     </Style>
  </Button.Style>
</Button>

If you however want to use the valueconverter approach all you need to do is use 'True' as the Value in your trigger bindings as such

<Condition Binding="{Binding ElementName=firstNameTxtBox, Path=Text.Length, Converter={StaticResource isButtonEnabledConverter}}" Value="True" />
<Condition Binding="{Binding ElementName=lastNameTxtBox, Path=Text.Length, Converter={StaticResource isButtonEnabledConverter}}" Value="True" />

Upvotes: 14

Salah Akbari
Salah Akbari

Reputation: 39976

You can use IsEnabled property of the button if you have one TextBox:

<Button Content="Save" Command="{Binding Save}" 
        IsEnabled="{Binding ElementName=firstNameTxtBox, Path=Text.Length, Mode=OneWay}" />

For both TextBoxes try this (You don't need to use converter):

<MultiDataTrigger.Conditions>
    <Condition Binding="{Binding ElementName=firstNameTxtBox, Path=Text.Length, Mode=OneWay}" Value="0"/>
    <Condition Binding="{Binding ElementName=lastNameTxtBox, Path=Text.Length, Mode=OneWay}" Value="0"/>
</MultiDataTrigger.Conditions>

Your complete code would be:

<TextBox Name="firstNameTxtBox" />
<TextBox Name="lastNameTxtBox" />

<Button Content="Save" Command="{Binding Save}" >
      <Button.Style>
          <Style TargetType="{x:Type Button}">
              <Style.Triggers>
                  <MultiDataTrigger>
                      <MultiDataTrigger.Conditions>
                         <Condition Binding="{Binding ElementName=firstNameTxtBox, Path=Text.Length, Mode=OneWay}" Value="0"/>
                         <Condition Binding="{Binding ElementName=lastNameTxtBox, Path=Text.Length, Mode=OneWay}" Value="0"/>
                      </MultiDataTrigger.Conditions>
                      <Setter Property="IsEnabled" Value="False"/>
                 </MultiDataTrigger>
             </Style.Triggers>
          </Style>
      </Button.Style>
</Button>

Upvotes: 11

Dennis
Dennis

Reputation: 37790

This will work without converter:

    <TextBox x:Name="Foo1"/>
    <TextBox x:Name="Foo2"/>
    <Button Content="Push me">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Text.Length, ElementName=Foo1, UpdateSourceTrigger=PropertyChanged}" Value="0"/>
                            <Condition Binding="{Binding Text.Length, ElementName=Foo2, UpdateSourceTrigger=PropertyChanged}" Value="0"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="IsEnabled" Value="False"/>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

Upvotes: 2

Nawed Nabi Zada
Nawed Nabi Zada

Reputation: 2875

Your converter is returning a boolean, so you definitely have to set your value to True.

But I would change my converter a little bit: Instead of:

return (int)value == 0 ? false:true;

I would do:

return ((int)value) !=0;

Upvotes: 0

Related Questions