views:

1141

answers:

6

I have overriden tabitem template and created my own custom style. however, I'm not sure how to write event triggers for mouse over event.

A: 

The best solution for using event triggers is to use Expression Blend. It comes with an intuitive way to create triggers.

Zied
A: 

If you truly want to use an EventTrigger you can do so like this

<Style x:TargetType="TabItem">
    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseOver">
          <BeginStoryboard>
            ....
          </BeinStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

In most cases If I am doing simple, discrete, value changes I will do it in a Property trigger that fires when the IsMouseOver property changes, as opposed to an EventTrigger which requires an animation

<Trigger Property="IsMouseOver" Value="True">
    <Setter Property="Foo" Value="Bar" />
</Trigger>
Foovanadil
+1  A: 

Thanks for all your respones. My triggers work fine. I just cant animate them. I had a simpler wat to do this in silverlight by using VisualStateManager and I am not sure how this is done in WPF.

I am providing my sample, as expression blend generated the copy of the template for a tabitem.

    <Style x:Key="StyleTabItem" TargetType="{x:Type TabItem}">
 <Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusStyle}"/>
 <Setter Property="Foreground" Value="{DynamicResource ForegroundGradient}"/>
 <Setter Property="BorderBrush" Value="{StaticResource TabItemGradientBrushUnselected}"/>
 <Setter Property="Background" Value="{StaticResource TabItemBorderBrushUnselected}"/>
 <Setter Property="Padding" Value="6,1,6,1"/>  
 <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
 <Setter Property="VerticalContentAlignment" Value="Stretch"/>
 <Setter Property="Template">
  <Setter.Value>
   <ControlTemplate TargetType="{x:Type TabItem}">
    <ControlTemplate.Resources>
     <Storyboard x:Key="Storyboard1">
      <DoubleAnimation
        Storyboard.TargetName="Bd" 
        Storyboard.TargetProperty="BorderBrush.GradientStops[0].Offset"
        Duration="00:00:00.3"/>
     </Storyboard>
    </ControlTemplate.Resources>
    <Grid SnapsToDevicePixels="true">
     <Border x:Name="Bd" 
     Background="{TemplateBinding Background}" 
     BorderBrush="{TemplateBinding BorderBrush}" 
     BorderThickness="1,1,1,0" 
     Padding="{TemplateBinding Padding}"
     CornerRadius="2,2,2,2">
      <ContentPresenter x:Name="Content" 
      HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
      VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
      ContentSource="Header" 
      RecognizesAccessKey="True"/>
     </Border>
    </Grid>
    <ControlTemplate.Triggers>
     <Trigger Property="IsMouseOver" Value="true">
      <Trigger.EnterActions>
       <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
      </Trigger.EnterActions>
      <Setter Property="Background" TargetName="Bd" Value="{StaticResource MouseOverGradientBrush}"/>
     </Trigger>
     <Trigger Property="Selector.IsSelected" Value="False"/>
     <Trigger Property="IsSelected" Value="true">
      <Setter Property="Panel.ZIndex" Value="1"/>
      <Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemGradientBrushSelected}"/>
      <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemBorderBrushSelected}"/>
     </Trigger>
     <MultiTrigger>
      <MultiTrigger.Conditions>
       <Condition Property="IsSelected" Value="false"/>
       <Condition Property="IsMouseOver" Value="true"/>
      </MultiTrigger.Conditions>
      <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemMouseOverGradientBorder}"/>
     </MultiTrigger>
     <MultiTrigger>
      <MultiTrigger.Conditions>
       <Condition Property="IsSelected" Value="true"/>
       <Condition Property="TabStripPlacement" Value="Top"/>
      </MultiTrigger.Conditions>
      <Setter Property="Margin" Value="-2,0,-2,0"/>
      <Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
     </MultiTrigger>
     <Trigger Property="IsEnabled" Value="false">
      <Setter Property="Background" TargetName="Bd" Value="{DynamicResource DisabledGradientBrush}"/>
      <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource DisabledGradientBorder}"/>
      <Setter Property="Foreground" Value="{DynamicResource DisabledForeground}"/>
     </Trigger>
    </ControlTemplate.Triggers>
   </ControlTemplate>
  </Setter.Value>
 </Setter>
</Style>

What i simply want to do (for a start) is on mouseover to change bd's background from the current value (whatever that is) to the value i have in the mouseover=true trigger (MouseOverGradientBrush). What is wrong in the above code and the animation doesnt work? I have used expression blend all i could...

immuner
+2  A: 

Hi Jason,

This should work. I pulled out a bunch of the triggers you had to help simplify things. If you get this working and need to add more features let me know and we can build it out from there.

I also replaced your Resource references with static colors. If you change them back to resources and it stops working then it is an issue with where your resources are at.

<LinearGradientBrush x:Key="MouseOverGradientBrush">
        <GradientStop Color="Black" Offset="0" />
        <GradientStop Color="Red" Offset="1" />
    </LinearGradientBrush>

 <Style x:Key="StyleTabItem"
           TargetType="{x:Type TabItem}">
        <Setter Property="Foreground"
                Value="{DynamicResource ForegroundGradient}" />
        <Setter Property="BorderBrush"
                Value="Black" />
        <Setter Property="Background"
                Value="Yellow" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid SnapsToDevicePixels="true">
                        <Border x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="1,1,1,0"
                                Padding="{TemplateBinding Padding}"
                                CornerRadius="2,2,2,2">
                            <ContentPresenter x:Name="Content"
                                              HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              ContentSource="Header"
                                              RecognizesAccessKey="True" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="{StaticResource MouseOverGradientBrush}" />
                        </Trigger>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Panel.ZIndex"
                                    Value="1" />
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="Cyan" />
                            <Setter Property="BorderBrush"
                                    TargetName="Bd"
                                    Value="Pink" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
Foovanadil
Hey Foovanadil yes that's working. Thank you. Now, is there a way to change to MouseOverGradientBrush on MouseOver event using a storyboard (not by specifying each offset separately, but rather specifying just the brush resource as a whole)?
immuner
Not sure what you mean. You want to change the actual brush resource to a different brush on the mouse over trigger? Can you explain the specific of your situation further? My gut reaction would be to specify different brush resources at design time and then swap which brush resource you are using in the trigger (as opposed to having one brush resource and trying to change it's contents). Is this approach not possible in your situation?
Foovanadil
A: 

Sorry for the late response, I am not getting a notification for comments (maybe this should be changed?). Ok, i will try to explain this further. I am not adding comment because i need to post example code. Let's say you have a control, any control. Let's say you have also defined a number of brushes as resources. So:

<LinearGradientBrush x:Key="NormalGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="NormalForeground">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Gray" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Red" Offset="0" />
    <GradientStop Color="Green" Offset="0.2" />
    <GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>

<RadialGradientBrush x:Key="MouseOverForeground" GradientOrigin="0.3,0.5">
    <GradientStop Color="Gray" Offset="0" />
    <GradientStop Color="Black" Offset="1" />
</RadialGradientBrush >

Now let's say you have the tab item control:

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<Style x:Key="StyleTabItem"
       TargetType="{x:Type TabItem}">
    <Setter Property="Foreground"
            Value="{StaticResource NormalForeground}" />
    <Setter Property="BorderBrush"
            Value="Black" />
    <Setter Property="Background"
            Value="{StaticResource NormalGradientBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="Bd"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="1,1,1,0"
                            Padding="{TemplateBinding Padding}">
                        <ContentPresenter x:Name="Content"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        SnapsToDevicePixels="True"
                        ContentSource="Header"
                        RecognizesAccessKey="True" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver"
                             Value="true">
                        // what here?
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

So the question is, how can i tell wpf to do a 3 second animation from the current brush to MouseOverGradientBrush and from the current foreground to MouseOverForeground on the MouseOver Event? I have seen in examples that you do that by changing offsets of gradient one by one. I do now want that. It increases the size of code and can end up being very messy. Besides brushes might have different number of offsets or one can be linear and the other one radial. I hope this is clearer.

immuner