自动开始故事板(C#)

时间:2017-10-22 06:28:11

标签: c# uwp

如果发生变化,我希望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>

3 个答案:

答案 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的值。

如果您想阅读更多内容:

MVVC-Pattern from MSDN

Data-Bindings in UWP

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