Create a simple wpf trigger on one object that affects another

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.