Search code examples
wpfdata-bindingstoryboardcaliburn.microdatatrigger

WPF Border Datatrigger strange behaviour


When I set the Value to "False" for the Binding={Binding IsCrit} the program seems to work fine but this is the opposite of what I need, because I only want the animation / storyboard to play when the hit of an ability was critical. I only want the color animation and storyboard to play if the IsCrit is "True". However when I set the Value to True then it never does the animation or storyboard.

When I set it to false, the "animation" is playing on every ability but when an Ability IsCrit is True, then the animation does not play for that item. Something seems to not work when I set the Datatrigger Value to True

I'm relatively new to WPF so most of the WPF has been snippets I've found online. Could this be to do with my Border being in a StackPanel?

The whole thing is wrapped inside a ListView.ItemTemplate, as maybe this could also be something to do with it not working.

<Border BorderBrush="{Binding ImageBorderColor}" Name="AbilityBorder"
                        BorderThickness="2"  Margin="0,0,10,0"
                        CornerRadius="8,8,8,8" RenderTransformOrigin=".5,.5"
                        Background="{Binding ImageBorderColor}">
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Style.Resources>
                                <Storyboard x:Key="CritAnimation" >
                                    <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color"
                                                    To="White" 
                                                    AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="Forever"
                                                    FillBehavior="HoldEnd" />                                     
                                </Storyboard>
                            </Style.Resources>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=IsCrit}" Value="False">
                                    <DataTrigger.EnterActions>
                                        <BeginStoryboard Name="flash" Storyboard="{StaticResource CritAnimation}" />
                                    </DataTrigger.EnterActions>
                                    <DataTrigger.ExitActions>
                                        <StopStoryboard BeginStoryboardName="flash" />
                                    </DataTrigger.ExitActions>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Border.RenderTransform>
                        <RotateTransform Angle="{Binding ImageAngle}" />
                    </Border.RenderTransform>
                    <Image x:Name="AbilityIcon" Source="{Binding ImageUrl}" Width="52" Height="52" 
                           RenderTransformOrigin=".5,.5">
                        <Image.RenderTransform>
                            <RotateTransform Angle="{Binding ImageAngle}" />
                        </Image.RenderTransform>
                    </Image>
                </Border>

Here is the FULL breakdown of my AbilityView.xaml.

   <ListView Name="AbilityList" 
          ItemsSource="{Binding LogLines}" 
          Background="{Binding BackgroundColor}" 
          Focusable="False" 
          Padding="10,10,0,0"
          IsTextSearchEnabled="False" 
          ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
          ScrollViewer.VerticalScrollBarVisibility="Disabled">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel cal:Message.Attach="[Event MouseLeftButtonUp] = [Action CopyToClipBoard($dataContext)]" x:Name="Item" Orientation="Horizontal" ToolTip="{Binding TooltipText}">
                <Border BorderBrush="{Binding ImageBorderColor}" Name="AbilityBorder"
                        BorderThickness="2"  Margin="0,0,10,0"
                        CornerRadius="8,8,8,8" RenderTransformOrigin=".5,.5"
                        Background="{Binding ImageBorderColor}">
                    <!--<Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Style.Resources>
                                <Storyboard x:Key="CritAnimation" >
                                    <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color"
                                                    To="White" 
                                                    AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="Forever"
                                                    FillBehavior="HoldEnd" />                                     
                                </Storyboard>
                            </Style.Resources>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=IsCrit}" Value="False">
                                    <DataTrigger.EnterActions>
                                        <BeginStoryboard Name="flash" Storyboard="{StaticResource CritAnimation}" />
                                    </DataTrigger.EnterActions>
                                    <DataTrigger.ExitActions>
                                        <StopStoryboard BeginStoryboardName="flash" />
                                    </DataTrigger.ExitActions>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>-->
                    <Border.RenderTransform>
                        <RotateTransform Angle="{Binding ImageAngle}" />
                    </Border.RenderTransform>
                    <Image x:Name="AbilityIcon" Source="{Binding ImageUrl}" Width="52" Height="52" 
                           RenderTransformOrigin=".5,.5">
                        <Image.RenderTransform>
                            <RotateTransform Angle="{Binding ImageAngle}" />
                        </Image.RenderTransform>
                    </Image>
                </Border>
                <custom:OutlinedText
                    VerticalAlignment="Center" Text="{Binding Text}" Visibility="{Binding TextVisibility}" FontSize="{Binding FontSize, FallbackValue=32}">
                </custom:OutlinedText>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="false" />
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <ScaleTransform x:Name="transform" />
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.10" />
                                <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.ScaleY" From="0" Duration="0:0:0.1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListView>

A new item is being inserted about every 1-2 seconds and so I am not needing to use a NotifyPropertyChanged event on the item. The other items are bound the same way, a new view model is being inserted into the collection used by the ListView.

The Caliburn micro click event is also working fine when copying to clipboard. The only problem im having is the with the event not firing when the Value is true. Does this DataTrigger only when there is a change?

Is there not some way to use a conditional trigger when a value is True?


Solution

  • This is how I fixed the problem I had. Use two different templates with an TemplateSelector implemented.

    public class AbilityItemTemplateSelector : DataTemplateSelector
    {
        public DataTemplate Critical { get; set; }
        public DataTemplate Normal { get; set; }
    
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var logItem = item as CombatLogViewModel;
    
            if (logItem != null)
            {
                return logItem.IsCrit ? Critical : Normal;
            }
    
            return base.SelectTemplate(item, container);
        }
    }
    
      <ListView Name="AbilityList" 
              ItemsSource="{Binding LogLines}" 
              Background="{Binding BackgroundColor}" 
              Focusable="False" 
              Padding="10,10,0,0"
              IsTextSearchEnabled="False" 
              ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
              ScrollViewer.VerticalScrollBarVisibility="Disabled">
        <ListView.Resources>
            <DataTemplate x:Key="CriticalTemplate">
                <StackPanel cal:Message.Attach="[Event MouseLeftButtonUp] = [Action CopyToClipBoard($dataContext)]" x:Name="Item" Orientation="Horizontal" ToolTip="{Binding TooltipText}">
                    <Border BorderThickness="2"  Margin="0,0,10,0"
                            CornerRadius="5,5,5,5" RenderTransformOrigin=".5,.5">
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.BorderBrush>
                        <Border.Background>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.Background>
                        <Border.Style>
                            <Style TargetType="{x:Type Border}">
                                <Setter Property="Background">
                                   <Setter.Value>
                                       <SolidColorBrush Color="{Binding ImageBorderColor}" />
                                   </Setter.Value>
                                </Setter>
                                <Style.Triggers>
                                    <EventTrigger RoutedEvent="Border.Loaded">
                                        <EventTrigger.Actions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ColorAnimation 
                                                        Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
                                                        From="Red" To="AliceBlue" 
                                                        Duration="00:00:0.500" AutoReverse="True" 
                                                        RepeatBehavior="Forever" />
                                                    <ColorAnimation 
                                                        Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                        From="Red" To="AliceBlue" 
                                                        Duration="00:00:0.500" AutoReverse="True" 
                                                        RepeatBehavior="Forever" />
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger.Actions>
                                    </EventTrigger>
                                </Style.Triggers>
                            </Style>
                        </Border.Style>
                        <Border.Triggers>
                            <EventTrigger RoutedEvent="Border.Loaded">
                                <EventTrigger.EnterActions>
                                    <BeginStoryboard Name="Flash">
                                        <Storyboard>
                                            <ColorAnimation 
                                                Storyboard.TargetProperty="BorderBrush.Color" 
                                                Storyboard.TargetName="Border"
                                                From="Red" To="AliceBlue" Duration="0:0:1.5" AutoReverse="True" 
                                                RepeatBehavior="Forever" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger.EnterActions>
                                <EventTrigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="Flash" />
                                </EventTrigger.ExitActions>
                            </EventTrigger>
                        </Border.Triggers>
                        <Border.RenderTransform>
                            <RotateTransform Angle="{Binding ImageAngle}" />
                        </Border.RenderTransform>
                        <Image x:Name="AbilityIcon" Source="{Binding ImageUrl}" Width="52" Height="52" 
                               RenderTransformOrigin=".5,.5">
                            <Image.RenderTransform>
                                <RotateTransform Angle="{Binding ImageAngle}" />
                            </Image.RenderTransform>
                        </Image>
                    </Border>
                    <custom:OutlinedText
                        VerticalAlignment="Center" Text="{Binding Text}" Visibility="{Binding TextVisibility}" FontSize="{Binding FontSize, FallbackValue=32}">
                    </custom:OutlinedText>
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="NormalTemplate">
                <StackPanel cal:Message.Attach="[Event MouseLeftButtonUp] = [Action CopyToClipBoard($dataContext)]" x:Name="Item" Orientation="Horizontal" ToolTip="{Binding TooltipText}">
                    <Border x:Name="AbilityBorder"
                            BorderThickness="2"  Margin="0,0,10,0"
                            CornerRadius="8,8,8,8" RenderTransformOrigin=".5,.5">
                        <Image x:Name="AbilityIcon" Source="{Binding ImageUrl}" Width="52" Height="52" 
                               RenderTransformOrigin=".5,.5">
                            <Image.RenderTransform>
                                <RotateTransform Angle="{Binding ImageAngle}" />
                            </Image.RenderTransform>
                        </Image>
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.BorderBrush>
                        <Border.Background>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.Background>
                        <Border.RenderTransform>
                            <RotateTransform Angle="{Binding ImageAngle}" />
                        </Border.RenderTransform>
                    </Border>
                    <custom:OutlinedText
                        VerticalAlignment="Center" Text="{Binding Text}" Visibility="{Binding TextVisibility}" FontSize="{Binding FontSize, FallbackValue=32}">
                    </custom:OutlinedText>
                </StackPanel>
            </DataTemplate>
        </ListView.Resources>
        <!--<ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel cal:Message.Attach="[Event MouseLeftButtonUp] = [Action CopyToClipBoard($dataContext)]" x:Name="Item" Orientation="Horizontal" ToolTip="{Binding TooltipText}">
                    <Border Name="AbilityBorder"
                            BorderThickness="2"  Margin="0,0,10,0"
                            CornerRadius="8,8,8,8" RenderTransformOrigin=".5,.5">
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.BorderBrush>
                        <Border.Background>
                            <SolidColorBrush Color="{Binding ImageBorderColor}" />
                        </Border.Background>
                        <Border.Style>
                            <Style TargetType="{x:Type Border}">
                                <Style.Triggers>
                                    <EventTrigger RoutedEvent="Border.Loaded">
                                        <EventTrigger.Actions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ColorAnimation 
                                                        Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
                                                        From="Red" To="AliceBlue" 
                                                        Duration="00:00:0.500" AutoReverse="True" 
                                                        RepeatBehavior="Forever" />
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger.Actions>
                                    </EventTrigger>
                                </Style.Triggers>
                            </Style>
                        </Border.Style>
                        <Border.RenderTransform>
                            <RotateTransform Angle="{Binding ImageAngle}" />
                        </Border.RenderTransform>
                        <Image x:Name="AbilityIcon" Source="{Binding ImageUrl}" Width="52" Height="52" 
                               RenderTransformOrigin=".5,.5">
                            <Image.RenderTransform>
                                <RotateTransform Angle="{Binding ImageAngle}" />
                            </Image.RenderTransform>
                        </Image>
                    </Border>
                    <custom:OutlinedText
                        VerticalAlignment="Center" Text="{Binding Text}" Visibility="{Binding TextVisibility}" FontSize="{Binding FontSize, FallbackValue=32}">
                    </custom:OutlinedText>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate-->
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="Focusable" Value="false" />
                <Setter Property="LayoutTransform">
                    <Setter.Value>
                        <ScaleTransform x:Name="transform" />
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <EventTrigger RoutedEvent="Loaded">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.10" />
                                    <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.ScaleY" From="0" Duration="0:0:0.1"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplateSelector>
            <custom:AbilityItemTemplateSelector 
                Normal="{StaticResource NormalTemplate}" 
                Critical="{StaticResource CriticalTemplate}" />
        </ListView.ItemTemplateSelector>
    </ListView>