我正在尝试使用Windows Phone 7 Silverlight项目中的VisualStateManager在UserControl上启动动画,但它不起作用。 GoToState只是继续返回false。
代码由VisualState行为组成,当更改datacontext上的State-property时,该行为运行GoToState,这在单击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";
}
}
答案 0 :(得分:2)
只是一个疯狂的猜测,但它可能是在错误的线程中执行吗?您可能希望使用调度程序在正确的(UI)线程上执行它。
GoToState是否在Button_Click函数中工作?
private void Button_Click(object sender, RoutedEventArgs e)
{
bool b = VisualStateManager.GoToState(this, "State2", false);
}
执行代码时调用TransitionToState。
这可以排除任何其他问题。
<强>更新强>
以下适用于我。我遇到了设置背景的一些问题。首先,这对UserControl没有任何影响,其次不能使用Color动画更改背景,这就是我改变不透明度的原因。
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";
}
我还建议使用ControlTemplates分配VisualStates,而不是直接在控件上定义它们。这将为您提供更大的灵活性,更好的维护等。
希望这有帮助。
答案 1 :(得分:0)
我有一个类似的问题,我找到了一个帮助我的解决方案,也许有人发现它很有用 如果usercontrol托管在layoutawarepage
中<my:usercontrole Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates" />
否则您将不得不遵循以下(示例可在布局识别页面中找到)
使用sizechanged创建事件处理程序
使用ApplicationView.Value检查视图状态
使用VisualStateManager.GoToState
编辑:很抱歉误解我认为它是winRT App