VisualStateManager无法启动动画的用户控件控件、无法启动、动画、用户

2023-09-05 01:27:04 作者:兔子国国王

我想开始使用VisualStateManager在Windows Phone 7的Silverlight项目一个用户控件一个动画,但它不会工作。 GoToState只是不停地返回false。

在code由的VisualState-行为,运行GoToState当上了DataContext的一个国家,房地产的用途改变,点击UI中的按钮时恰好的:

我是什么做错了吗?

XAML:

 <电网>
        <用户控件X:名称=_ testSubjectL:VisualStates.CurrentState ={结合国家}/>
        <按钮VerticalAlignment =底部CONTENT =更改状态点击=Button_Click/>
        < VisualStateManager.VisualStateGroups>
            < VisualStateGroup>
                <的VisualState X:名称=状态2>
                    <情节板>
                        < ColorAnimation从=红色为=绿色持续时间=0:0:10Storyboard.TargetProperty =背景Storyboard.TargetName =_ testSubject/>
                    < /故事板>
                < /的VisualState>
            < / VisualStateGroup>
        < /VisualStateManager.VisualStateGroups>
    < /网格>
 

C#:

 公共类测试:INotifyPropertyChanged的
{
    公共事件PropertyChangedEventHandler的PropertyChanged;
    无效OnPropertyChanged(字符串名称){如果(的PropertyChanged!= NULL)的PropertyChanged(这一点,新PropertyChangedEventArgs(名称)); }
    串_state;
    公共字符串州{{返回_state; } {设置_STATE =价值; OnPropertyChanged(国家); }}
}

公共静态类VisualStates
{
    公共静态只读的DependencyProperty CurrentStateProperty =
        DependencyProperty.RegisterAttached(currentState的typeof运算(字符串)的typeof(VisualStates),新PropertyMetadata(TransitionToState));

    公共静态字符串GetCurrentState(DependencyObject的OBJ)
    {
        返回(串)obj.GetValue(CurrentStateProperty);
    }

    公共静态无效SetCurrentState(DependencyObject的OBJ,字符串值)
    {
        obj.SetValue(CurrentStateProperty,价值);
    }

    私有静态无效TransitionToState(对象发件人,DependencyPropertyChangedEventArgs参数)
    {
        控制C =发送者作为对照;
        如果(C!= NULL)
        {
            布尔B = VisualStateManager.GoToState(C,(串)args.NewValue,假);
        }
        其他
        {
            抛出新的ArgumentException(currentState的是仅支持控制型);
        }
    }

公共部分MainPage的类:PhoneApplicationPage
{
    MainPage的市民(){的InitializeComponent(); }

    私人无效PhoneApplicationPage_Loaded(对象发件人,RoutedEventArgs E)
    {
        _testSubject.DataContext =新的测试();
    }

    私人无效Button_Click(对象发件人,RoutedEventArgs E)
    {
        ((测试)_testSubject.DataContext).State =状态2;
    }
}
 

解决方案

只是胡乱猜测,但会不会是它是被在错误的线程中执行?您可能需要使用调度到正确的(UI)线程上执行它。

是否GoToState工作的Button_Click功能?

 私人无效Button_Click(对象发件人,RoutedEventArgs E)
{
    布尔B = VisualStateManager.GoToState(这一点,状态2,假);
}
 
暴风影音可以打开flash文件吗

当你执行你的code为TransitionToState被调用。

这将排除任何其他问题。

更新

我下面的作品。我来到翻过一些问题,设置背景。首先,这不会对一个用户控件任何影响,第二个它是不可能使用一个彩色的动画,这就是为什么我改变不透明度为改变背景。

MainPage.xaml中

 <电网X:名称=的ContentPanel
      Grid.Row =1
      保证金=12,0,12,0>
    < Grid.RowDefinitions>
        < RowDefinition />
        < RowDefinition />
        < RowDefinition身高=*/>
    < /Grid.RowDefinitions>
    < L:系统testControl X:名称=_ testSubject
                   Grid.Row =0
                   L:VisualStates.CurrentState ={结合国家}/>

    <用户控件X:名称=_ test2Subject
                 高度=100
                 Grid.Row =1
                 L:VisualStates.CurrentState ={结合国家}>
        <电网X:名称=aLayoutRoot
              背景=小麦>
            < VisualStateManager.VisualStateGroups>
                < VisualStateGroup X:名称=CommonStates>
                    <的VisualState X:名称=状态2>
                        <情节板>
                            < D​​oubleAnimation是Storyboard.TargetName =aLayoutRoot
                                             Storyboard.TargetProperty =透明度
                                             从=1
                                             为=0
                                             持续时间=0:0:2
                                             自动翻转=真/>
                        < /故事板>
                    < /的VisualState>
                < / VisualStateGroup>
            < /VisualStateManager.VisualStateGroups>
        < /网格>
    < /用户控件>

    <按钮单击=Button_Click
            内容=点击
            Grid.Row =2/>


< /网格>
 

TestControl.xaml

 <用户控件X:类=PhoneApp1.TestControl
    的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
    的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
    的xmlns:D =htt​​p://schemas.microsoft.com/ex$p$pssion/blend/2008
    的xmlns:MC =htt​​p://schemas.openxmlformats.org/markup-compatibility/2006
    MC:可忽略=D
    的FontFamily ={的StaticResource PhoneFontFamilyNormal}
    字号={的StaticResource PhoneFontSizeNormal}
    前景={的StaticResource PhoneForegroundBrush}
    D:DesignHeight =480D:DesignWidth =480>

    <电网X:名称=LayoutRoot背景=小麦>
        < VisualStateManager.VisualStateGroups>
            < VisualStateGroup X:名称=CommonStates>
                <的VisualState X:名称=状态2>
                    <情节板>
                        < D​​oubleAnimation是Storyboard.TargetName =LayoutRoot
                                         Storyboard.TargetProperty =透明度
                                         从=1
                                         为=0
                                         持续时间=0:0:2
                                         自动翻转=真/>
                    < /故事板>
                < /的VisualState>
            < / VisualStateGroup>
        < /VisualStateManager.VisualStateGroups>
    < /网格>
< /用户控件>
 

test.cs中/ TransitionToState方法

 私有静态无效TransitionToState(对象发件人,DependencyPropertyChangedEventArgs参数)
{
    用户控件C =发件人为用户控件;
    如果(C = NULL和放大器;!&安培;!args.NewValue = NULL)
    {
        布尔B = VisualStateManager.GoToState(C,(串)args.NewValue,真正的);
        变种A = B;
    }
}
 

MainPage.cs

  MainPage的公()
{
    的InitializeComponent();

    _testSubject.DataContext =新的测试();
    _test2Subject.DataContext =新的测试();

}

私人无效Button_Click(对象发件人,RoutedEventArgs E)
{
    ((测试)_testSubject.DataContext).State =状态2;
    ((测试)_test2Subject.DataContext).State =状态2;
}
 

我也建议使用CONTROLTEMPLATES分配直接在控制定义它们的VisualStates代替。这会给你更多的灵活性,更好的维护等。

希望这有助于。

I'm trying to start a animation on a UserControl using the VisualStateManager in a Windows Phone 7 Silverlight project but it won't work. GoToState just keep returning false.

The code consists of a VisualState-behaviour which is running the GoToState when a State-property on the datacontext is changed, which happens when the button in the UI is clicked:

What am I doing wrong?

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

解决方案

just a wild guess, but could it be that it is being executed in the wrong thread? You might want to use the dispatcher to execute it on the correct (UI) thread.

Does the GoToState work in the Button_Click function ?

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

And is TransitionToState being called when you execute your code.

This would rule out any other problems.

UPDATE

The following works for me. I came accross some problems with setting the Background. First of all this doesn't have any effect on a UserControl and second it is not possible to change the background using a Color animation that's why I change the opacity.

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 method

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

I would also recommend using ControlTemplates to assign VisualStates instead of defining them directly on the control. This will give you more flexibility, better maintenance, etc..

Hope this helps.