visual studio samples page developing change bootstrap apps c# uwp

c# - studio - uwp vs wpf



Comience automáticamente el guión gráfico(C#) (3)

Quiero que Storyboard comience automáticamente si algo cambia: - Por ejemplo, tengo un bloque de texto que puede contener texto "Encendido" o "Apagado"

<TextBlock Name="BindedTextBlock" />

para comprobar si el texto del bloque de texto está activado o desactivado, creé DispatcherTimer (sugiérame de otra manera si puede verificar el texto del bloque de texto)

si el texto del bloque de texto está activado, NextStoryBoardIn.Begin (); debería comenzar, si el texto del bloque de texto está DESACTIVADO entonces PrevStoryBoardOut.Begin (); debería comenzar. así que lo hice de esta manera:

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();

funciona bien pero el guión gráfico se dispara continuamente, debería comenzar una vez. y si escribo

if(BindedTextBlock.Text.Equals("On")) { PrevStoryBoardIn.Begin(); } else if(BindedTextBlock.Text.Equals("Off")) { PrevStoryBoardOut.Begin(); } timer.Stop();

entonces nunca revisará el texto del bloque de texto nuevamente, incluso si el texto del bloque de texto está actualizado.

Actualizar

si alguien se interesaba en ver códigos Xaml para fines de prueba, entonces compartí alguna muestra de mi 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>


Inicializa su temporizador con TimeSpan.FromSeconds(0) . Así que su Tick-callback se llamará permanentemente.

Una posible solución sería tener un modelo de vista

Primero el ViewModel en sí mismo:

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 { }; }

Y aquí la parte lógica. Como puede ver, no necesita un temporizador, que verifica cada x segundos si algo cambia.

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(); } }

Ahora puede definir un disparador o un convertidor para mostrar "ENCENDIDO" o "APAGADO" dependiendo del valor de su modelo de vista.

Si quieres leer un poco más:

Patrón MVVC de MSDN

Enlaces de datos en UWP


Si está jugando con animaciones, considere hacerlo en XAML. Hay muchas opciones, sin mencionar Comportamientos . Eche un vistazo a esta muestra :

<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>

Código detrás:

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


Usar DispatcherTimer no es una buena idea.

No hay evento TextChanged para TextBlock . Entonces podemos crear uno y realizar su tarea en él.

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(); }