3

Windows Phone 7 Silverlight プロジェクトで VisualStateManager を使用して UserControl でアニメーションを開始しようとしていますが、うまくいきません。GoToState は false を返し続けます。

コードは、データ コンテキストの State プロパティが変更されたときに GoToState を実行する VisualState 動作で構成されます。これは、UI のボタンがクリックされたときに発生します。

私は何を間違っていますか?

XAML:

    <Grid>
        <UserControl x:Name="_testSubject" l:VisualStates.CurrentState="{Binding State}" />
        <Button VerticalAlignment="Bottom" Content="Change state" Click="Button_Click" />
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="State2">
                    <Storyboard>
                        <ColorAnimation From="Red" To="Green" Duration="0:0:10" Storyboard.TargetProperty="Background" Storyboard.TargetName="_testSubject" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>

C#:

public class Test : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged(string name) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); }
    string _state;
    public string State { get { return _state; } set { _state = value; OnPropertyChanged("State"); } }
}

public static class VisualStates
{
    public static readonly DependencyProperty CurrentStateProperty =
        DependencyProperty.RegisterAttached("CurrentState", typeof(String), typeof(VisualStates), new PropertyMetadata(TransitionToState));

    public static string GetCurrentState(DependencyObject obj)
    {
        return (string)obj.GetValue(CurrentStateProperty);
    }

    public static void SetCurrentState(DependencyObject obj, string value)
    {
        obj.SetValue(CurrentStateProperty, value);
    }

    private static void TransitionToState(object sender, DependencyPropertyChangedEventArgs args)
    {
        Control c = sender as Control;
        if (c != null)
        {
            bool b = VisualStateManager.GoToState(c, (string)args.NewValue, false);
        }
        else
        {
            throw new ArgumentException("CurrentState is only supported on the Control type");
        }
    }

public partial class MainPage : PhoneApplicationPage
{
    public MainPage() { InitializeComponent(); }

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
        _testSubject.DataContext = new Test();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ((Test)_testSubject.DataContext).State = "State2";
    }
}
4

2 に答える 2

2

単なる推測ですが、間違ったスレッドで実行されている可能性がありますか? ディスパッチャーを使用して、正しい (UI) スレッドで実行することをお勧めします。

GoToState は Button_Click 関数で機能しますか?

private void Button_Click(object sender, RoutedEventArgs e)
{
    bool b = VisualStateManager.GoToState(this, "State2", false);
}

また、コードを実行すると TransitionToState が呼び出されます。

これにより、他の問題が排除されます。

アップデート

以下は私にとってはうまくいきます。背景の設定でいくつかの問題に遭遇しました。まず第一に、これは UserControl には何の影響も与えません。次に、カラー アニメーションを使用して背景を変更することはできないため、不透明度を変更します。

MainPage.xaml

<Grid x:Name="ContentPanel"
      Grid.Row="1"
      Margin="12,0,12,0">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <l:TestControl x:Name="_testSubject"
                   Grid.Row="0"
                   l:VisualStates.CurrentState="{Binding State}" />

    <UserControl x:Name="_test2Subject"
                 Height="100"
                 Grid.Row="1"
                 l:VisualStates.CurrentState="{Binding State}">
        <Grid x:Name="aLayoutRoot"
              Background="Wheat">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="State2">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="aLayoutRoot"
                                             Storyboard.TargetProperty="Opacity"
                                             From="1"
                                             To="0"
                                             Duration="0:0:2"
                                             AutoReverse="True" />
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </Grid>
    </UserControl>

    <Button Click="Button_Click"
            Content="Click"
            Grid.Row="2" />


</Grid>

TestControl.xaml

<UserControl x:Class="PhoneApp1.TestControl"
    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"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid x:Name="LayoutRoot" Background="Wheat">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="State2">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="LayoutRoot"
                                         Storyboard.TargetProperty="Opacity"
                                         From="1"
                                         To="0"
                                         Duration="0:0:2"
                                         AutoReverse="True" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</UserControl>

Test.cs / TransitionToState メソッド

private static void TransitionToState(object sender, DependencyPropertyChangedEventArgs args)
{
    UserControl c = sender as UserControl;
    if (c != null && args.NewValue != null)
    {
        bool b = VisualStateManager.GoToState(c, (string)args.NewValue, true);
        var a = b;
    }
}

MainPage.cs

public MainPage()
{
    InitializeComponent();

    _testSubject.DataContext = new Test();
    _test2Subject.DataContext = new Test();

}

private void Button_Click(object sender, RoutedEventArgs e)
{
    ((Test)_testSubject.DataContext).State = "State2";
    ((Test)_test2Subject.DataContext).State = "State2"; 
}

VisualStates をコントロールに直接定義するのではなく、ControlTemplates を使用して割り当てることもお勧めします。これにより、柔軟性が向上し、メンテナンスが改善されます。

お役に立てれば。

于 2011-08-22T02:57:12.010 に答える