繁体   English   中英

自动开始故事板(C#)

[英]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的值。

如果你想再读一些:

来自MSDN的MVVC-Pattern

UWP中的数据绑定

如果您正在玩动画,请考虑在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM