Pregunta

Estoy intentando utilizar el Silverlight DataStateBehavior, que funciona bien en la mayoría de los casos en que hago clic en un botón que conjuntos dicen que un 'Selected' Propiedad en la vista del modelo ya sea falsa o verdadera. El DataStateBehavior entonces le dice al VisualStateManager para ir al estado correspondiente.

De esta manera:

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

lo anterior funciona bien. Lo que estoy tratando de hacer es sin embargo para conseguir que se establece el estado correcto cuando se carga la aplicación, si tuviera que establecer la propiedad 'seleccionados' en el modelo de vista true de forma predeterminada yo no ver ningún cambio en la interfaz de usuario hasta he hecho clic en el botón para cambiar la propiedad de modelo de vista.

Sé que hay varias clases involucradas con la materia DataState incluyendo:

  • BindingListener.cs
  • ConverterHelper.cs
  • DataStateBehavior.cs
  • DataStateSwitchBehavior.cs
  • DataTrigger.cs

Cualquier pista sería bueno, Gracias

¿Fue útil?

Solución

de hecho voy a añadir una segunda respuesta que he intentado, y parece ser más limpio, ya que se puede hacer todo en XAML y sin un comportamiento personalizado. Voy a dejar la otra respuesta simplemente como una referencia para una solución alternativa, ya que tanto el trabajo.

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

Sólo necesitará al añadir una referencia a los Microsoft.Expression.Interactions de montaje que forma parte del SDK de mezcla.

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

Otros consejos

Prueba esta extensión de la clase DataStateBehavior. Cuando se carga el elemento de destino, la DataStateBehavior será evaluar como si la propiedad se ha actualizado.

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));
        }
    }
}

Una forma He resuelto este problema es hacer que un comportamiento que puede agregar a su control para ponerlo en un estado visual inicial durante la carga. Aquí está un ejemplo sencillo:

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);
    }
}

A continuación, sólo tiene que añadir que el comportamiento del nivel de control de usuario en XAML:

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

También podría modificar fácilmente esto para aceptar una lista separada por comas de los estados iniciales que luego se podría dividir y recorrer si necesitaba para poner el control en un montón de diferentes estados mutuamente excluyentes después de la carga separada.

Esto podría también ser rediseñado en un TriggerAction que usted podría desencadenar el evento Loaded del control, no estoy seguro de cuál sería la forma más limpia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top