Search code examples
wpfxamldatatrigger

Grid level triggers that set grid's child properties


Is it possible to define triggers at the grid level that update grid's child properties?

I tried something like that but without success:

ViewModel:

public class MyViewModel
{
    public bool PropertyA {get;set;}
    public bool PropertyB {get;set;}
}

(I omitted all the PropertyChanged stuff for brievety)

XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>

    <TextBlock x:Name="ControlA" Grid.Row="0" />

    <TextBlock x:Name="ControlB" Grid.Row="1" />

    <Grid.Triggers>
        <!-- Condition A -->
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding PropertyA}" Value="false"/>
                <Condition Binding="{Binding PropertyB}" Value="true"/>
            </MultiDataTrigger.Conditions>
            <MultiDataTrigger.Setters>
                <Setter TargetName="ControlA" Property="Text" Value="Blah"/>
                <Setter TargetName="ControlB" Property="Text" Value="Blah"/>
            </MultiDataTrigger.Setters>
        </MultiDataTrigger>
        <!-- Conditon B -->
        <MultiDataTrigger>
             <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding PropertyA}" Value="false"/>
                <Condition Binding="{Binding PropertyB}" Value="false"/>
            </MultiDataTrigger.Conditions>
            <MultiDataTrigger.Setters>
                <Setter TargetName="ControlA" Property="Text" Value="Blah"/>
                <Setter TargetName="ControlB" Property="Text" Value="Blah"/>
            </MultiDataTrigger.Setters>
        </MultiDataTrigger>
        <!-- Condition C -->
        <DataTrigger Binding="{Binding PropertyA}" Value="true">
             <Setter TargetName="ControlA" Property="Text" Value="Blah"/>
             <Setter TargetName="ControlB" Property="Text" Value="Blah"/>
        </DataTrigger>
    </Grid.Triggers>
</Grid>

But the compiler complains about

The name "ControlA" is not recognized.

The name "ControlB" is not recognized.

The member "Text" is not recognized or is not accessible.

The member "Text" is not recognized or is not accessible.


Solution

  • Is it possible to define triggers at the grid level that update grid's child properties?

    No. Setting the TargetName of a Setter only makes sense in a ControlTemplate where there is an element with a matching name.

    Generally speaking, a Setter can only set a property of the element to which the style or trigger is applied to.

    What you should do instead is to create a style with triggers for the TextBlock(s), e.g.:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding PropertyA}" Value="false"/>
                            <Condition Binding="{Binding PropertyB}" Value="true"/>
                        </MultiDataTrigger.Conditions>
                        <MultiDataTrigger.Setters>
                            <Setter Property="Text" Value="Blah"/>
                        </MultiDataTrigger.Setters>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Resources>
    
        <TextBlock x:Name="ControlA" Grid.Row="0" />
    
        <TextBlock x:Name="ControlB" Grid.Row="1" />
    
    </Grid>