67 votes

La définition d'une propriété avec un EventTrigger

Je veux être en mesure de définir une propriété avec un EventTrigger, il y a un certain nombre de problèmes avec cela.

1) EventTriggers seulement des Actions de soutien, donc, je dois utiliser un storyBoard pour définir mes propriétés.

2) une Fois que j'utilise un story-board, j'ai deux options:

  • Arrêt: une Fois que l'animation a cessé de la valeur revient à l'avant de l'animation a commencé
  • HoldEnd: Cela verrouille la propriété, de sorte que ni le code, ni d'interaction de l'utilisateur peut modifier la propriété que l'animation est maintenant.

Dans l'exemple ci-dessous, je tiens à mettre l'IsChecked valeur False à la propriété lorsque le bouton est cliqué et je veux que l'utilisateur puisse modifier la IsChecked et/ou je veux être en mesure de modifier la propriété dans le code.

Exemple:

<EventTrigger
    SourceName="myButton"
    RoutedEvent="Button.Click">
    <EventTrigger.Actions>
        <BeginStoryboard>
            <Storyboard>
                <BooleanAnimationUsingKeyFrames
                    Storyboard.TargetName="myCheckBox"
                    Storyboard.TargetProperty="IsChecked"
                    FillBehavior="Stop">
                    <DiscreteBooleanKeyFrame
                        KeyTime="00:00:00"
                        Value="False" />
                </BooleanAnimationUsingKeyFrames>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger.Actions>
</EventTrigger>

Je me rends compte que je peux utiliser le "Terminé" événement après le storyboard complète pour définir la valeur False. Cependant, dans ce cas je tiens à contenir la logique dans le code XAML, que cette logique peut être utilisé sur un contrôle personnalisé et n'est spécifique à l'INTERFACE utilisateur.

35voto

Neutrino Points 1261

Il suffit de créer votre propre action.

namespace WpfUtil
{
    using System.Reflection;
    using System.Windows;
    using System.Windows.Interactivity;


    /// <summary>
    /// Sets the designated property to the supplied value. TargetObject
    /// optionally designates the object on which to set the property. If
    /// TargetObject is not supplied then the property is set on the object
    /// to which the trigger is attached.
    /// </summary>
    public class SetPropertyAction : TriggerAction<FrameworkElement>
    {
        // PropertyName DependencyProperty.

        /// <summary>
        /// The property to be executed in response to the trigger.
        /// </summary>
        public string PropertyName
        {
            get { return (string)GetValue(PropertyNameProperty); }
            set { SetValue(PropertyNameProperty, value); }
        }

        public static readonly DependencyProperty PropertyNameProperty
            = DependencyProperty.Register("PropertyName", typeof(string),
            typeof(SetPropertyAction));


        // PropertyValue DependencyProperty.

        /// <summary>
        /// The value to set the property to.
        /// </summary>
        public object PropertyValue
        {
            get { return GetValue(PropertyValueProperty); }
            set { SetValue(PropertyValueProperty, value); }
        }

        public static readonly DependencyProperty PropertyValueProperty
            = DependencyProperty.Register("PropertyValue", typeof(object),
            typeof(SetPropertyAction));


        // TargetObject DependencyProperty.

        /// <summary>
        /// Specifies the object upon which to set the property.
        /// </summary>
        public object TargetObject
        {
            get { return GetValue(TargetObjectProperty); }
            set { SetValue(TargetObjectProperty, value); }
        }

        public static readonly DependencyProperty TargetObjectProperty
            = DependencyProperty.Register("TargetObject", typeof(object),
            typeof(SetPropertyAction));


        // Private Implementation.

        protected override void Invoke(object parameter)
        {
            object target = TargetObject ?? AssociatedObject;
            PropertyInfo propertyInfo = target.GetType().GetProperty(
                PropertyName,
                BindingFlags.Instance|BindingFlags.Public
                |BindingFlags.NonPublic|BindingFlags.InvokeMethod);

            propertyInfo.SetValue(target, PropertyValue);
        }
    }
}

Dans ce cas, je suis de la liaison à la propriété DialogResult sur mon viewmodel.

<Grid>

    <Button>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <wpf:SetPropertyAction PropertyName="DialogResult" TargetObject="{Binding}"
                                       PropertyValue="{x:Static mvvm:DialogResult.Cancel}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        Cancel
    </Button>

</Grid>

22voto

Sergey Aldoukhov Points 8386

Autant que j'aime XAML, pour ce genre de tâches que j'ai passer le code derrière. Comportements attachés sont un bon motif pour cela. Gardez à l'esprit, Expression Blend 3 fournit un moyen standard pour programmer et utiliser des comportements. Il y a quelques existants sur l'Expression de la Communauté du Site.

6voto

rmoore Points 9561

L'arrêt de la table de montage séquentiel peut être fait dans le code-behind, ou le code xaml, selon l'endroit où la nécessité vient de.

Si l'EventTrigger est déplacée à l'extérieur de la touche, alors nous pouvons aller de l'avant et de les cibler avec un autre EventTrigger qui dira le storyboard d'arrêter. Lorsque le storyboard est arrêté de cette manière, il ne reviendra pas à la valeur précédente.

Ici, j'ai déplacé le Bouton.Cliquez sur EventTrigger à un StackPanel et a ajouté un nouveau EventTrigger sur la Case à cocher.Cliquez sur pour arrêter le Bouton du storyboard, lorsque la Case est cliqué. Cela nous permet de cocher et décocher la Case à cocher lorsqu'il est cliqué sur et nous donne souhaité en décochant le comportement de la touche.

    <StackPanel x:Name="myStackPanel">

		<CheckBox x:Name="myCheckBox"
				  Content="My CheckBox" />

		<Button Content="Click to Uncheck"
				x:Name="myUncheckButton" />

		<Button Content="Click to check the box in code."
				Click="OnClick" />

		<StackPanel.Triggers>

			<EventTrigger RoutedEvent="Button.Click"
						  SourceName="myUncheckButton">
				<EventTrigger.Actions>
					<BeginStoryboard x:Name="myBeginStoryboard">
						<Storyboard x:Name="myStoryboard">
							<BooleanAnimationUsingKeyFrames Storyboard.TargetName="myCheckBox"
															Storyboard.TargetProperty="IsChecked">
								<DiscreteBooleanKeyFrame KeyTime="00:00:00"
														 Value="False" />
							</BooleanAnimationUsingKeyFrames>
						</Storyboard>
					</BeginStoryboard>
				</EventTrigger.Actions>
			</EventTrigger>

			<EventTrigger RoutedEvent="CheckBox.Click"
						  SourceName="myCheckBox">
				<EventTrigger.Actions>
					<StopStoryboard BeginStoryboardName="myBeginStoryboard" />
				</EventTrigger.Actions>
			</EventTrigger>

		</StackPanel.Triggers>
	</StackPanel>

Pour arrêter le storyboard dans le code derrière, nous aurons à faire quelque chose de légèrement différent. Le troisième bouton permet à la méthode où nous nous arrêterons à la table de montage séquentiel et définissez la propriété IsChecked retour à la réalité grâce à un code.

Nous ne pouvons pas appeler myStoryboard.Stop() parce que nous n'avons pas commencé le Storyboard par le code de la isControllable paramètre. Au lieu de cela, nous pouvons supprimer la table de montage séquentiel. Pour ce faire nous avons besoin de la FrameworkElement que le storyboard existe, dans ce cas, notre StackPanel. Une fois le storyboard est retiré, nous pouvons une fois de définir la propriété IsChecked avec la persistance de l'INTERFACE utilisateur.

	private void OnClick(object sender, RoutedEventArgs e)
	{
		myStoryboard.Remove(myStackPanel);
		myCheckBox.IsChecked = true;
	}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X