1

私は現在、何を処理するのが最善かわからないというシナリオに直面しています。

シナリオ:

  1. ControlAには2つのカスタムビジュアルステートがあり、それらを「StateOn」と「StateOff」と呼びましょう。
  2. ここで、ControlAにテンプレートを適用します。これを「templateA」と呼びましょう。
  3. 「templateA」には、タイプControlB(StateOn / Offを認識しない)のコントロールが1つあります。
  4. ControlBには、ControlAの視覚的な状態の変更、つまりStateOnとStateOffを処理するテンプレートがあります。

問題:
ControlBは、ControlAで起動されたVisualStatesへの変更を受け取らないため、視覚的な変更は発生しません。

問題は、ルート要素がコントロール(ControlB)であることに関係していると思います。これは、目的の状態でgotostateを起動しません。ただし、ControlAの視覚状態の変化をControlBに伝播するための最も簡単でクリーンな方法は何でしょうか。

ご協力いただきありがとうございます!

ヘンリー

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>

背後にあるコード:

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
{

}
4

1 に答える 1

0

まず、ControlAとControlBの両方に。の依存関係プロパティが必要です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);
    }

あなたの直感に反して、視覚的な状態はまったく伝播しません。状態は、それらが直接接続されているコントロールに対してのみ意味があります。ただし、この依存関係プロパティを両方のコントロールに追加すると、テンプレートバインディングを介してプロパティ値を伝播できるようになります。-

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

元のControlAコードについては、このm_isSetフィールドは不要になりました。-

public void ToggleState()
{
    IsSet = !IsSet;
}
于 2010-08-19T21:19:43.353 に答える