Question

Je suis actuellement confronté à un scénario que je ne suis pas sûr quelle est la meilleure façon de gérer.

Scénario:

  1. ControlA a 2 deux visualstates personnalisés, nous allons les appeler « StateOn » et « StateOff ».
  2. je fais ma demande un modèle sur ControlA, permettent de faire appel de ce « templateA ».
  3. « templateA » a un contrôle en dessous du type ControlB (qui est pas au courant de StateOn / Off).
  4. ControlB a un modèle qui gère les changements de visualSTATE de ControlA, à savoir, StateOn et StateOff.

Problème: ControlB ne reçoit pas des modifications aux VisualStates ont tiré sur ControlA, donc pas de changements visuels se produisent.

Je pense que le problème a à voir avec l'élément racine étant un contrôle (ControlB), qui n'a pas gotostate de feu sur les états désirés. Cependant, je me demande ce qui est le plus simple / propre moyen de propager les changements de visualSTATE de ControlA à ControlB.

Merci pour votre aide!

Henry

Xaml: -

<UserControl x:Class="VisualStateChangePropagation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:VisualStateChangePropagation"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="20"/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>

            <SolidColorBrush x:Name="Fill_Bg_Red" Color="Red"/>
            <SolidColorBrush x:Name="Fill_Bg_Blue" Color="Blue"/>

            <ControlTemplate x:Name="templateA" TargetType="Control">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="Common">
                            <VisualState x:Name="StateOn">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="m_rect"
                                                                   Storyboard.TargetProperty="(Rectangle.Fill)">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Fill_Bg_Red}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="StateOff"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Rectangle x:Name="m_rect" Fill="{StaticResource Fill_Bg_Blue}"/>
                </Grid>
            </ControlTemplate>

            <ControlTemplate x:Name="templateB" TargetType="Control">
                <local:ControlB Template="{StaticResource templateA}"/>
            </ControlTemplate>

        </Grid.Resources>
        <local:ControlA x:Name="m_control1" Template="{StaticResource templateA}" Grid.Column="0"/>
        <Button Click="Button_Click" Grid.Column="1" Content="swap"/>
        <local:ControlA x:Name="m_control2" Template="{StaticResource templateB}" Grid.Column="2"/>
    </Grid>
</UserControl>
code

derrière:

public class ControlA : Control
{
    public void ToggleState()
    {
        m_isSet = !m_isSet;
        UpdateVisualState();
    }

    private void UpdateVisualState()
    {
        string targetState = m_isSet ? "StateOn" : "StateOff";
        VisualStateManager.GoToState(this, targetState, false);
    }

    private bool m_isSet = false;
}

public class ControlB : Control
{

}
Était-ce utile?

La solution

D'abord les deux ControlA et ControlB devrait avoir une propriété de dépendance pour IsSet.

    public bool IsSet
    {
        get { return (bool)GetValue(IsSetProperty); }
        set { SetValue(IsSetProperty, value); }
    }

    public static readonly DependencyProperty IsSetProperty =
            DependencyProperty.Register(
                    "IsSet",
                    typeof(bool),
                    typeof(ControlA),  //Change in ControlB
                    new PropertyMetadata(false, OnIsSetPropertyChanged));

    private static void OnIsSetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Control source = d as Control;
         string newState = (bool)e.NewValue ? "StateOn" : "StateOff";
         VisualStateManager.GotoState(source, newState, true);
    }

Contrairement à vos états d'intuition visuelle ne se propagent pas du tout. Les États ne sont meaningfull au contrôle auquel ils sont directement rattachés. Cependant, avec cette propriété de dépendance ajoutée aux deux commandes que vous pouvez propager la valeur de la propriété par modèle de liaison: -

        <ControlTemplate x:Name="templateB" TargetType="Control">
            <local:ControlB Template="{StaticResource templateA}" IsSet="{TemplateBinding IsSet}" />
        </ControlTemplate>

En ce qui concerne votre code d'origine ControlA le champ m_isSet n'est plus nécessaire: -

public void ToggleState()
{
    IsSet = !IsSet;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top