如果发生变化,我希望Storyboard自动开始: - 例如,我有文本块,可以包含文本“开”或“关”
<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>
答案 0 :(得分:3)
使用DispatcherTimer
不是一个好主意。
TextChanged
没有TextBlock
个事件。因此,我们可以创建一个并在其中执行您的任务。
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();
}
答案 1 :(得分:2)
您使用TimeSpan.FromSeconds(0)
初始化计时器。因此,您的Tick-callback将被永久调用。
一种可能的解决方案是拥有一个viewmodel
首先是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();
}
}
现在您可以定义一个触发器或转换器来显示&#34; ON&#34;或&#34; OFF&#34;取决于ViewModel的值。
如果您想阅读更多内容:
答案 2 :(得分:2)
如果您正在玩动画,请考虑在XAML中进行。有很多选择,没有提及行为。看看at this sample:
<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";
}