Can Triggers affect elements they are not applied to?

I have this program here that consists of a Label and a Button.  I have a Style that contains a trigger that says that when someone mouse overs the button the button background should turn yellow.  But let's say I wanted the label to also turn yellow when someone mouses over the button.  How can I have a Trigger applied to one element (in this case, the button) affect other elements around it   I know you can do this in code, but how can this be accomplished in XAML

 

<Window x:Class="WindowsApplication3.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WindowsApplication3" Height="300" Width="300"

>

<Window.Resources>

<Style TargetType="{x:Type Button}" x:Key="yellowButton">

<Style.Triggers>

<Trigger Property="IsMouseOver" Value="True">

<Setter Property="Background" Value="Yellow" />

</Trigger>

</Style.Triggers>

</Style>

</Window.Resources>

<StackPanel>

<Label Margin="10">My Label</Label>

<Button Width="150" Height="100" Style="{StaticResource yellowButton}">My Button</Button>

</StackPanel>

</Window>

 

-Ryan



Answer this question

Can Triggers affect elements they are not applied to?

  • RobMiles

    Hmmm...still doesn't like it....

  • Saravanan.Chinnusamy

    It is easier to do this in code than XAML

  • Tom25

    TargetName in Template.Triggers is restricted to the subset of child objects within the Template. This is imposed as an encapsulation boundary. Same with how a Style can only affect the properties on the object being styled.

    TargetName outside Template.Triggers are unbounded and unstructured - if any element can dictate property values of any other element, you start weaving a complex web of dependencies. Or even worse, the occasional infinite loop. (There are implementation challenges as well, but we don't need to get into that here.)

    Think of all the "Programming 101" lessons about why the "GOTO" command is bad in a programming language. GOTO exists because it is necessary in certain scenarios, but most language purists would rather rip them out because they're so easily abused.

    Yes - you can do this from C# code. You can also use "goto" in C#, but that doesn't mean either of them are necessarily good ideas.

    These are powerful tools... and they can be used for good or evil. Take care in wielding your powers. [Insert Dark Side of the Force joke here.]



  • Gurpreet Singh Gill

    Oh I'm sorry...try putting your trigger on Window.Triggers instead of Style.Triggers.

    <Window x:Class="WindowsApplication3.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="WindowsApplication3" Height="300" Width="300"

    >

    <Window.Triggers>

    <Trigger SourceName="MyButton" Property="IsMouseOver" Value="True">

    <Setter Property="Background" Value="Yellow" />
    <Setter TargetName="MyLabel"  Property="Background" Value="Yellow" />

    </Trigger>

    </Window.Triggers>

    <StackPanel>

    <Label x:Name="MyLabel" Margin="10">My Label</Label>

    <Button x:Name="MyButton" Width="150" Height="100" >My Button</Button>

    </StackPanel>

    </Window>



  • hank voight

    <Setter TargetName="MyLabel" Property="Background" Value="Yellow"/>
    <Setter Property="Background" Value="Yellow"/>

    That doesn't compile. It gives the error 'TargetName property cannot be set on a Style Setter'


  • James Alexander

    Setting the TargetName should work, however it cannot work in a style. If you think about it, it makes sense: if you set the target name in the style in what scope should the runtime look for the name
    So you could try to set target name but in the triggers of the element itself, not in the style.


  • Lynn Trapp

    TargetName can only be used in ControlTemplate.Triggers it appears.

  • Linda Shao

    something like this would work

    <StackPanel>

    <Label Margin="10" x:Name="lbl">My Label</Label>

    <Button Width="150" Height="100" Style="{StaticResource yellowButton}" x:Name="btn1">My Button

    </Button>

    <StackPanel.Triggers>

    <EventTrigger RoutedEvent="Button.MouseMove" SourceName="btn1">

    <EventTrigger.Actions>

    <BeginStoryboard>

    <Storyboard>

    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="lbl" Storyboard.TargetProperty="(Label.Background)">

    <DiscreteObjectKeyFrame KeyTime="0:0:0">

    <DiscreteObjectKeyFrame.Value>

    <SolidColorBrush Color="Yellow"/>

    </DiscreteObjectKeyFrame.Value>

    </DiscreteObjectKeyFrame>

    </ObjectAnimationUsingKeyFrames>

    </Storyboard>

    </BeginStoryboard>

    </EventTrigger.Actions>

    </EventTrigger>

    <EventTrigger RoutedEvent="Button.MouseLeave" SourceName="btn1">

    <EventTrigger.Actions>

    <BeginStoryboard>

    <Storyboard>

    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="lbl" Storyboard.TargetProperty="(Label.Background)">

    <DiscreteObjectKeyFrame KeyTime="0:0:0">

    <DiscreteObjectKeyFrame.Value>

    <SolidColorBrush Color="White"/>

    </DiscreteObjectKeyFrame.Value>

    </DiscreteObjectKeyFrame>

    </ObjectAnimationUsingKeyFrames>

    </Storyboard>

    </BeginStoryboard>

    </EventTrigger.Actions>

    </EventTrigger>

    </StackPanel.Triggers>

    </StackPanel>



  • pcesarfe

    Looks like we're in a catch-22.

    MSDN wrote:

    Note that the collection of triggers established on an element only supports event triggers, not property triggers. If you require property triggers, you must place these within a style and then assign that style to the element either directly via the Style property, or indirectly through type-based style reference.

    Elements only support event triggers. Styles don't support targetname. What to do



  • Nickeay

    Lee d

    That does work but it's more complicated.  Is there a way to do this with a Trigger rather than with an EventTrigger so that you can work with Properties instead of with events, storyboards, and animations   Also with this method the values have to be manually reset, rather than resetting automatically as they do with you use a Trigger.  I'm just trying to figure out all this trigger stuff.  It seems forcing people to create animations and keyframes just to change a property value can't be the right way to do this.

    -Ryan

     

     


  • ReinerZ

    Definitely...definitely easier in code. Unless you were to define a custom control for this grouping. Assuming that it even merits being its own control.

  • Benin

    More simple than that, a Setter can have a TargetName. So give your Label a Name and define two setters, one that sets your button and the other that sets your Label by using the TargetName property.

    <Setter TargetName="MyLabel" Property="Background" Value="Yellow"/>
    <Setter Property="Background" Value="Yellow"/>

    That should do what you want.



  • Can Triggers affect elements they are not applied to?