DataTrigger on each item's textbox in ItemsControl

649 views Asked by At

I have an ItemsControl that displays a list of Labels & TextBoxes that are used for data input and a button that executes some command when pressed (using the input values):

<DataTemplate x:Key="StringParameterTemplate">
    <StackPanel Name="StackPanel_Parameter"
                Orientation="Horizontal">
        <Label Name="ParameterLabel"
               Content="{Binding ParameterLabel}"
               HorizontalContentAlignment="Right"
               Width="200" />
        <TextBox Name="ParameterTextBlock"
                 Text="{Binding ParameterValue, UpdateSourceTrigger=PropertyChanged}"
                 Width="300"/>
    </StackPanel>
</DataTemplate>

        . . .

        <!-- Display all parameters -->
        <ItemsControl Name="ListView_Parameters"
                      ItemsSource="{Binding ParameterCollection, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
                      ItemTemplateSelector="{StaticResource TaskParameterTemplateSelector}"
                      BorderThickness="0" />

<Button Name="ExecuteTaskButton"
        Content="{Binding ButtonLabel}"
        Style="{StaticResource ExecuteButtonStyle}"
        Command="ExecuteTask">

I would like to create a style that enables/disables the button when ANY of the parameters from ListView_Parameters is empty. Something like this:

<!-- Execute button enable / disable -->
<Style x:Key="ExecuteButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Button.IsEnabled" Value="True" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding ElementName=ListView_Parameters, Path=ParameterValue}" Value="">
            <Setter Property="IsEnabled" Value="False" />
        </DataTrigger>    
    </Style.Triggers>
</Style>
1

There are 1 answers

2
James Harcourt On

You can achieve this with a single binding using a converter.

<Button Content="{Binding ButtonLabel}"
        IsEnabled="{Binding Path=ItemsSource, 
                            RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, 
                            Converter={local:ItemsToBooleanConverter}}" />

Then your converter takes an input of the itemssource (for example a list of objects) - and can return true if all fields you want have values, false otherwise.

The converter is mostly boilerplate, but would look like something this:

public class ItemsToBooleanConverter : MarkupExtension, IValueConverter

... but the important part would like like this, if you were using a list:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var items = value as IList<ParameterList>;
        return !(items.Any( <you check here for empty values> );
    }

You'll need to be sure your parameter entry fields are bound properly to their sources so that the converter check is current.