Trouble with DataTriggers when the bindings rarely -- if ever -- change
We are using an ObservableCollection that contains elements of type MyItem, where a MyItem contains a field called MyItemCategory that is an enum. In our xaml we have data triggers that look like this:
The category of each item can change at runtime, but in practice rarely does, which means the value of MyItemCategory isn't changing and therefore the above triggers aren't firing (I am assuming that the value is set before the view loads). We tried adding this trigger to account for that as a test:
With the above LoadedEventTrigger hack, the FIRST element of the list isn't properly transitioning into the MyItemCategoryA state, but all subsequent list elements are. Furthermore, there doesn't seem to be a way to switch states based on the bound value in MyItemCategory with this approach, so it doesn't really solve the problem.
Is there some other way we should go about doing this? Is there a bug here?
Code: Select all
<b:DataTrigger Binding="{Binding MyItemCategory}" Comparison="Equal" Value="{x:Static definitions:MyItemCategory.None}">
<b:GoToStateAction x:Name="MyItemCategoryNoneTrigger" StateName="MyItemCategoryNone" TargetName="Root"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding MyItemCategory}" Comparison="Equal" Value="{x:Static definitions:MyItemCategory.CategoryA}">
<b:GoToStateAction x:Name="MyItemCategoryATrigger" StateName="MyItemCategoryA" TargetName="Root"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding MyItemCategory}" Comparison="Equal" Value="{x:Static definitions:MyItemCategory.CategoryB}">
<b:GoToStateAction x:Name="MyItemCategoryBTrigger" StateName="MyItemCategoryB" TargetName="Root"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding MyItemCategory}" Comparison="Equal" Value="{x:Static definitions:MyItemCategory.CategoryC}">
<b:GoToStateAction x:Name="MyItemCategoryCTrigger" StateName="MyItemCategoryC" TargetName="Root"/>
</b:DataTrigger>Code: Select all
<b:EventTrigger EventName="Loaded">
<b:GoToStateAction x:Name="LoadedEventTrigger" StateName="MyItemCategoryA" TargetName="Root"/>
</b:EventTrigger>Is there some other way we should go about doing this? Is there a bug here?
-
-
sfernandez
Site Admin
- Posts: 3364
- Joined:
Re: Trouble with DataTriggers when the bindings rarely -- if ever -- change
Hi Rachelle,
DataTriggers will evaluate the binding the first time they are attached or when the data context changes, so it doesn't matter if the property in your items changes or not. The corresponding visual state should be activated depending on the current value of the property. If the visual state is not changing then it must be a bug.
I tried a simple example with a collection of items and similar data triggers and it works as expected, each item gets its own color depending on the category:
Could you please point me how to reproduce it in your repository so I can debug it?
DataTriggers will evaluate the binding the first time they are attached or when the data context changes, so it doesn't matter if the property in your items changes or not. The corresponding visual state should be activated depending on the current value of the property. If the visual state is not changing then it must be a bug.
I tried a simple example with a collection of items and similar data triggers and it works as expected, each item gets its own color depending on the category:
Code: Select all
using System.Collections.ObjectModel;
using UnityEngine;
using Testing;
namespace Testing
{
public enum ItemCategory
{
None,
CategoryA,
CategoryB,
CategoryC
}
public class MyItem
{
public string Name { get; set; }
public ItemCategory Category { get; set; }
}
public class VM
{
public ObservableCollection<MyItem> Items { get; set; }
}
}
public class DataTriggerTest : MonoBehaviour
{
void Start()
{
NoesisView view = GetComponent<NoesisView>();
VM vm = new VM { Items = new ObservableCollection<MyItem>() };
vm.Items.Add(new MyItem { Name = "Item1", Category = ItemCategory.CategoryA });
vm.Items.Add(new MyItem { Name = "Item2", Category = ItemCategory.CategoryB });
vm.Items.Add(new MyItem { Name = "Item3", Category = ItemCategory.CategoryB });
vm.Items.Add(new MyItem { Name = "Item4", Category = ItemCategory.CategoryC });
vm.Items.Add(new MyItem { Name = "Item5", Category = ItemCategory.CategoryA });
vm.Items.Add(new MyItem { Name = "Item6", Category = ItemCategory.CategoryC });
vm.Items.Add(new MyItem { Name = "Item7", Category = ItemCategory.CategoryB });
vm.Items.Add(new MyItem { Name = "Item8", Category = ItemCategory.CategoryA });
vm.Items.Add(new MyItem { Name = "Item9", Category = ItemCategory.CategoryC });
view.Content.DataContext = vm;
}
}Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:Testing">
<Grid.Resources>
<DataTemplate x:Key="itemTemplate">
<Grid x:Name="root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CategoryStates">
<VisualState x:Name="None">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background.Color">
<EasingColorKeyFrame KeyTime="0" Value="Silver"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CategoryA">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background.Color">
<EasingColorKeyFrame KeyTime="0" Value="Red"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CategoryB">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background.Color">
<EasingColorKeyFrame KeyTime="0" Value="Green"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CategoryC">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background.Color">
<EasingColorKeyFrame KeyTime="0" Value="Blue"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="bd" Background="Black" Margin="2" Padding="20,10">
<TextBlock Text="{Binding Name}" TextAlignment="Center" Foreground="White"/>
</Border>
<Decorator x:Name="interaction">
<b:Interaction.Triggers>
<b:DataTrigger Binding="{Binding Category}" Value="{x:Static local:ItemCategory.None}">
<b:GoToStateAction TargetName="root" StateName="None"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding Category}" Value="{x:Static local:ItemCategory.CategoryA}">
<b:GoToStateAction TargetName="root" StateName="CategoryA"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding Category}" Value="{x:Static local:ItemCategory.CategoryB}">
<b:GoToStateAction TargetName="root" StateName="CategoryB"/>
</b:DataTrigger>
<b:DataTrigger Binding="{Binding Category}" Value="{x:Static local:ItemCategory.CategoryC}">
<b:GoToStateAction TargetName="root" StateName="CategoryC"/>
</b:DataTrigger>
</b:Interaction.Triggers>
</Decorator>
</Grid>
</DataTemplate>
</Grid.Resources>
<ItemsControl Width="200" Height="400" ItemsSource="{Binding Items}" ItemTemplate="{StaticResource itemTemplate}"/>
</Grid>Who is online
Users browsing this forum: No registered users and 2 guests