web-dev-qa-db-fra.com

wpf - déclenche le datatrigger quand la propriété change indépendamment de la nouvelle valeur

J'essaie d'exécuter une animation sur une cellule d'une grille de données lorsque la valeur de la cellule de la grille de données change.

La grille de données elle-même est liée à une collection ObservableCollection d'anciens objets CLR simples. Dans ce cas, disons que les objets sont des objets "Personne" avec des propriétés pour "Prénom", "Nom" et "Age". La classe 'Person' implémente l'interface INotifyPropertyChanged et chaque propriété a l'appel approprié pour onPropertyChanged dans son setter.

Tout va bien. Dans la définition de grille de données, j'ai défini mon DataTemplate pour dessiner chaque cellule et attaché un datatrigger ... comme suit:

<DataGridTemplateColumn Header="FirstName">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Border Name="templateBorder">
                <TextBlock Name="templateTextBlock" Text="{Binding Path=FirstName}" />
            </Border>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=FirstName}" Value="Richard">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard AutoReverse="True">
                                <DoubleAnimation Storyboard.TargetName="templateTextBlock" Storyboard.TargetProperty="Opacity" To=".1" Duration="0:0:.5" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Lorsqu'un objet de mon ObservableCollection est mis à jour (j'ai modifié la valeur Prénom), la grille de données est mise à jour correctement. Comme dans l'exemple ci-dessus, si j'ai changé la valeur de FirstName en 'Richard', l'animation est également exécutée correctement.

Mon problème est que je dois exécuter mon animation, quelle que soit la nouvelle valeur de Firstname. J'ai parcouru le Web, mais certains ne semblent trouver que des exemples de déclencheurs par rapport à une valeur connue, par exemple. déclencheur d'incendie lorsque FirstName est «Richard», comme je l'ai démontré dans mon exemple.

Ma question est: comment puis-je déclencher le datatrigger indépendamment de la valeur de la propriété mise à jour? En résumé, comment puis-je déclencher le datatrigger chaque fois que la propriété FirstName est mise à jour pour une ligne donnée de la grille de données.

Merci beaucoup.

22
Peanut

Grâce aux indications tirées des réponses à cette question, j'ai trouvé que la réponse consistait à utiliser un EventTrigger et le TargetUpdated RoutedEvent.

<DataTemplate>
    <Border Name="templateBorder">
        <TextBlock Name="templateTextBlock" Text="{Binding Path=FirstName, NotifyOnTargetUpdated=True}" />
    </Border>
    <DataTemplate.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard AutoReverse="True">
                    <DoubleAnimation Storyboard.TargetName="templateTextBlock" Storyboard.TargetProperty="Opacity" To=".1" Duration="0:0:.5" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

Au-delà de EventTrigger, la seule autre chose requise était de définir 'NotifyOnTargetUpdated = True' lors de la configuration de la liaison pour le bloc de texte.

Merci.

41
Peanut

Il semble que vous ayez besoin d'un EventTrigger "do X lorsqu'un événement se produit" au lieu d'un DataTrigger.

Pas essayé moi-même .. mais il devrait être possible de déclencher votre événement personnalisé FirstNameChanged et de faire exécuter les actions-déclencheurs en réponse à cela.

1
Gishu
  <Storyboard x:Key="MessageStoryBoardEntry" FillBehavior="Stop">

            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                <EasingDoubleKeyFrame KeyTime="0:0:00.30" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:03" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:03.20" Value="1500"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>

        <Storyboard x:Key="MessageStoryBoardExit" FillBehavior="Stop">

            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                <EasingDoubleKeyFrame KeyTime="0:0:0.001" Value="1500"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
1
Bathineni

Vous pouvez essayer de définir le DataContext du TextBlock sur la propriété FirstName, puis utiliser le DataContextChanged event.

Vous pouvez également utiliser PropertyChanged event et filtrer pour la propriété souhaitée.

De toute façon, je pense que vous allez devoir utiliser un événement.

0
Ray

Pourriez-vous pirater quelque chose avec un convertisseur de valeur? 

<DataTrigger Binding="{Binding Path=FirstName, Converter=FirstNameConverter}" Value="MakeItSo">

et

class FirstNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return "MakeItSo";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
...
    }
}

J'imagine que cela dépend si WPF appelle le convertisseur à chaque changement de propriété ou s'il évalue d'abord la valeur. Je n'ai pas essayé, c'est juste une pensée ...

0
MarcE