[英]Automatically Begin Storyboard (C#)
我希望故事板在事情发生变化时自动开始: - 例如,我有文本块,可以包含文本“开”或“关”
<TextBlock Name="BindedTextBlock" />
用于检查文本块文本是打开还是关闭我创建DispatcherTimer(如果可以检查文本块文本,建议我任何其他方式)
如果textblock文本为ON,则NextStoryBoardIn.Begin(); 应该开始,如果文本块文本为OFF,那么PrevStoryBoardOut.Begin(); 应该开始。 所以我这样做:
DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0) };
timer.Tick += delegate (object sender, object e)
{
if(BindedTextBlock.Text.Equals("On"))
{
PrevStoryBoardIn.Begin();
}
else if(BindedTextBlock.Text.Equals("Off"))
{
PrevStoryBoardOut.Begin();
}
};
timer.Start();
它工作正常,但故事板不断触发,它应该开始一次。 如果我写
if(BindedTextBlock.Text.Equals("On"))
{
PrevStoryBoardIn.Begin();
}
else if(BindedTextBlock.Text.Equals("Off"))
{
PrevStoryBoardOut.Begin();
}
timer.Stop();
那么即使文本块文本被更新,它也永远不会再次检查文本块文本。
更新
如果任何一个有兴趣查看Xaml代码用于测试目的,所以我分享了一些我的xaml样本
<Page.Resources>
<Storyboard x:Name="PrevStoryBoardIn">
<DoubleAnimation Storyboard.TargetName="AppearStackPanel" Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:1"/>
</Storyboard>
<Storyboard x:Name="PrevStoryBoardOut">
<DoubleAnimation Storyboard.TargetName="AppearStackPanel" Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:1"/>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="DogWatcherTextBlock"
Height="50" Width="100" VerticalAlignment="Top"/>
<StackPanel x:Name="AppearStackPanel" BorderThickness="1" BorderBrush="Crimson" Height="150" Width="150" Opacity="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<!-- My Items -->
</StackPanel>
</Grid>
使用DispatcherTimer
不是一个好主意。
TextBlock
没有TextChanged
事件。 因此,我们可以创建一个并在其中执行您的任务。
public MainPage()
{
this.InitializeComponent();
//Register PropertyChangedCallback
MyTextBlock.RegisterPropertyChangedCallback(TextBlock.TextProperty, OnTextChanged);
}
private void OnTextChanged(DependencyObject sender, DependencyProperty dp)
{
if(((TextBlock)sender).Text == "On")
PrevStoryBoardIn.Begin();
else if(((TextBlock)sender).Text == "Off")
PrevStoryBoardOut.Begin();
}
使用TimeSpan.FromSeconds(0)
初始化计时器。 因此,您的Tick-callback将被永久调用。
一种可能的解决方案是拥有一个视图模型
首先是ViewModel本身:
public class ViewModel : INotifyPropertyChanged
{
private bool _someVariable;
public bool SomeVariable
{
get { return _someVariable; }
set
{
//// simplified code
_someVariable = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(SomeVariable)));
SomeVariableChanged(this, EventArgs.Empty);
}
}
public event EventHandler SomeVariableChanged = delegate { };
/// <summary>
/// Needed for updating the binding
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
这里是逻辑部分。 如您所见,您不需要计时器,如果有变化,它会每x秒检查一次。
var viewModel = new ViewModel();
_textBlock.DataContext = viewModel; //// Here you bind your viewmodel to the TextBlock
viewModel.SomeVariableChanged += (s, e) =>
{
if(viewModel.SomeVariable == true)
{
PrevStoryBoardIn.Begin();
}
else
{
PrevStoryBoardOut.Begin();
}
}
现在,您可以定义触发器或转换器以显示“ON”或“OFF”,具体取决于ViewModel的值。
如果你想再读一些:
如果您正在玩动画,请考虑在XAML中进行。 有很多选择,没有提到行为 。 看一下这个样本 :
<Page.Resources>
<local:EqualParamConverter x:Key="EqualParamConverter"/>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TextStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="OnState">
<Storyboard>
<DoubleAnimation Duration="0:0:1" Storyboard.TargetName="myRectangle" Storyboard.TargetProperty="Opacity" To="1.0"/>
</Storyboard>
<VisualState.StateTriggers>
<StateTrigger IsActive="{Binding ElementName=myTextBlck, Path=Text, Converter={StaticResource EqualParamConverter}, ConverterParameter='On'}"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="OffState">
<Storyboard>
<DoubleAnimation Duration="0:0:1" Storyboard.TargetName="myRectangle" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
<VisualState.StateTriggers>
<StateTrigger IsActive="{Binding ElementName=myTextBlck, Path=Text, Converter={StaticResource EqualParamConverter}, ConverterParameter='Off'}"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="myTextBlck" Text="Something"/>
<Rectangle x:Name="myRectangle" Width="300" Height="100" Fill="Green" Opacity="0.75"/>
<ToggleButton Content="Switcher" Click="ToggleButton_Click"/>
</StackPanel>
代码背后:
public class EqualParamConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language) => value.ToString() == parameter.ToString();
public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
}
public sealed partial class MainPage : Page
{
public MainPage() { this.InitializeComponent(); }
private void ToggleButton_Click(object sender, RoutedEventArgs e) => myTextBlck.Text = (bool)(sender as ToggleButton).IsChecked ? "On" : "Off";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.