Question

Je suis en train d'utiliser Silverlight DataStateBehavior, il fonctionne très bien dans la plupart des cas où je clique sur un bouton qui définit dire un « sélectionné » la propriété dans le modèle de vue soit vrai ou faux. Le DataStateBehavior dit alors le VisualStateManager d'aller à l'État concerné.

Comme ceci:

   <Button...>
   <i:Interaction.Behaviors>
             <id:DataStateBehavior Binding="{Binding Selected}" Value="True" TrueState="SelectedVisualState" FalseState="DeselectedVisualState"/>
          </i:Interaction.Behaviors>
   </Button>

Les travaux ci-dessus bien. Ce que je suis en train de faire est bien de le faire pour définir l'état correct lorsque les charges d'application, si je devais définir la propriété « Sélectionné » sur le modèle de vue true par défaut, je ne vois pas de changements dans l'interface utilisateur jusqu'à ce que J'ai cliqué sur le bouton pour changer la propriété viewmodel.

Je sais qu'il ya plusieurs classes impliquées dans les choses DataState y compris:

  • BindingListener.cs
  • ConverterHelper.cs
  • DataStateBehavior.cs
  • DataStateSwitchBehavior.cs
  • DataTrigger.cs
Tous les indices serait bon

, Merci

Était-ce utile?

La solution

Je vais en fait d'ajouter une deuxième réponse que je viens d'essayer, et semble être plus propre, car il peut être fait tout en XAML et sans comportement personnalisé. Je vais laisser l'autre réponse comme une référence pour une solution alternative car ils travaillent tous les deux.

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <ic:GoToStateAction StateName="SelectedVisualState"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

Vous aurez juste besoin à ajouter une référence à l'ensemble de Microsoft.Expression.Interactions qui fait partie du SDK Blend.

xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"

Autres conseils

Essayer cette extension de la classe DataStateBehavior. Lorsque les charges de l'élément cible, le DataStateBehavior sera évaluer comme si la propriété a été mis à jour.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace Gusdor.Wpf
{
    /// <summary>
    /// Fix for data state behavior. Behavior will trigger transitions when target element loads.
    /// </summary>
    class DataStateBehaviorFix: Microsoft.Expression.Interactivity.Core.DataStateBehavior
    {
        public bool UseTransitionsOnLoad { get; set; }

        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.Loaded += AssociatedObject_Loaded;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.Loaded -= AssociatedObject_Loaded;
        }

        void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            Evaluate();
        }

        void Evaluate()
        {
            if (Value == null)
            {
                GotoState(Binding == null, this.AssociatedObject);
            }
            else GotoState(Value.Equals(Binding), this.AssociatedObject);
        }

        /// <summary>
        /// Attempts to change to the named state. Walks up tree to first match.
        /// </summary>
        /// <param name="flag"></param>
        /// <param name="element"></param>
        void GotoState(bool flag, FrameworkElement element)
        {          
            string stateName = flag ? TrueState : FalseState;

            if (HasState(element, stateName))
            {
                bool ret = System.Windows.VisualStateManager.GoToElementState(element, stateName, UseTransitionsOnLoad);
            }
            else if (element.Parent as FrameworkElement != null)
                GotoState(flag, element.Parent as FrameworkElement);
        }
        /// <summary>
        /// Checks if an element has the state named
        /// </summary>
        /// <param name="element"></param>
        /// <param name="stateName"></param>
        /// <returns></returns>
        bool HasState(FrameworkElement element, string stateName)
        {
            var groups = Microsoft.Expression.Interactivity.VisualStateUtilities.GetVisualStateGroups(element).Cast<VisualStateGroup>();

            return groups.Any(p => p.States.Cast<VisualState>().Any(s => s.Name == stateName));
        }
    }
}

Une façon que je l'ai résolu ce problème est de faire un comportement que vous pouvez ajouter à votre commande pour le mettre dans un état visuel initial lors du chargement. Voici un exemple simple:

public class InitialVisualStateBehavior : Behavior<Control>
{
    public static readonly DependencyProperty InitialStateProperty = DependencyProperty.Register(
        "InitialState",
        typeof(string),
        typeof(InitialVisualStateBehavior),
        null);

    public string InitialState
    {
        get { return (string)GetValue(InitialStateProperty); }
        set { SetValue(InitialStateProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
        }
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        VisualStateManager.GoToState(this.AssociatedObject, this.InitialState, false);
    }
}

Vous pouvez ensuite ajouter que le comportement au niveau UserControl en XAML:

<i:Interaction.Behaviors>
    <myi:InitialVisualStateBehavior InitialState="SelectedVisualState" />
</i:Interaction.Behaviors>

Vous pouvez modifier facilement ce à accepter une liste séparée par des virgules des états initiaux que vous pouvez ensuite diviser et boucler si vous avez besoin de mettre le contrôle dans un tas de différents états mutuellement exclusifs après le chargement.

Cela pourrait aussi être dans un TriggerAction refactorisé que vous pourriez déclencher de l'événement Loaded du contrôle, je ne suis pas sûr de quelle manière serait plus propre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top