Create a simple wpf trigger on one object that affects another

Bluebaron picture Bluebaron · Nov 17, 2010 · Viewed 35k times · Source

This is the closest that I have come to creating a simple trigger on this. I just want the datagrid's IsMouseOver == true to show the button. The problem is that the Setter's TargetName says: The property 'TargetName' does not represent a valid target for the 'Setter' because an element named 'ButtonExpand' was not found. Make sure that the target is declared before any Setters, Triggers or Conditions that use it. What am I doing wrong?

<UserControl.Resources>
    <Style TargetType="DataGrid">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="ButtonExpand" Property="Visibility" Value="Visible" />
            </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>
<Grid>



    <DataGrid Name="MainDataGrid" ItemsSource="{Binding Programs}" IsReadOnly="True" AutoGenerateColumns="false" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            <DataGridTextColumn Header="Version" Binding="{Binding Version}"/>
            <DataGridTextColumn Header="Publisher" Binding="{Binding Publisher}"/>
        </DataGrid.Columns>
    </DataGrid>

    <Button Name="ButtonExpand" Height="25" Width="25" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="Hidden">+</Button>
</Grid>

Answer

Fredrik Hedblad picture Fredrik Hedblad · Nov 17, 2010

TargetName is not intended for use within the Triggers collection of a Style. A style does not have a namescope, so it does not make sense to refer to elements by name there. But a template (either DataTemplate or ControlTemplate) does have a namescope.

See this link.

You can do it the other way around with a DataTrigger for the Button. Note that you must set the Property Visibility within the Style for the DataTrigger to work.

<Grid Name="MainGrid"> 

    <DataGrid ItemsSource="{Binding Programs}"
              IsReadOnly="True"
              AutoGenerateColumns="false" > 
      <DataGrid.Columns> 
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/> 
        <DataGridTextColumn Header="Version" Binding="{Binding Version}"/> 
        <DataGridTextColumn Header="Publisher" Binding="{Binding Publisher}"/> 
      </DataGrid.Columns> 
    </DataGrid> 

    <Button Name="ButtonExpand"
            Height="25"
            Width="25"
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Content="+">
        <Button.Style>
            <Style TargetType="Button">
                <Setter Property="Visibility" Value="Hidden"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=MainGrid,
                                                   Path=IsMouseOver}" 
                                 Value="True">
                        <Setter Property="Visibility" Value="Visible" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>
</Grid>

Another way to do it would be to bind Visibilty of ButtonExpand to the IsMouseOver property of the DataGrid with a converter.