wpf num scroll up
//uc.xaml <UserControl x:Class="WpfApp201.UCScrollNum" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WpfApp201" mc:Ignorable="d" d:DesignHeight="180" d:DesignWidth="150"> <Grid> <Grid> <Grid.RowDefinitions> <RowDefinition Height="180"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="50"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Border Background="#F0F0F0" CornerRadius="5" BorderThickness="1" BorderBrush="#CCCCCC" Grid.Row="0" Grid.Column="1"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock x:Name="numTbk1" Text="0" FontSize="50" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" Visibility="{Binding UpTbkVisibility,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" /> <TextBlock x:Name="numTbk2" Text="0" FontSize="50" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" Visibility="{Binding MiddleTbkVisibility,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> <TextBlock x:Name="numTbk3" Text="0" FontSize="50" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center" Visibility="{Binding DownTbkVisibility,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </Grid> </Border> </Grid> </Grid> </UserControl> //uc.xaml.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp201 { /// <summary> /// Interaction logic for UCScrollNum.xaml /// </summary> public partial class UCScrollNum : UserControl, INotifyPropertyChanged { public UCScrollNum() { InitializeComponent(); this.DataContext = this; } public bool UCIsIncremented { get { return (bool)GetValue(UCIsIncrementedProperty); } set { SetValue(UCIsIncrementedProperty, value); } } // Using a DependencyProperty as the backing store for UCIsIncremented. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCIsIncrementedProperty = DependencyProperty.Register("UCIsIncremented", typeof(bool), typeof(UCScrollNum), new PropertyMetadata(true, OnUCIsIncrementedChanged)); private static void OnUCIsIncrementedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { } public Visibility UpTbkVisibility { get { return (Visibility)GetValue(UpTbkVisibilityProperty); } set { SetValue(UpTbkVisibilityProperty, value); } } // Using a DependencyProperty as the backing store for UpTbkVisibility. This enables animation, styling, binding, etc... public static readonly DependencyProperty UpTbkVisibilityProperty = DependencyProperty.Register("UpTbkVisibility", typeof(Visibility), typeof(UCScrollNum), new PropertyMetadata(Visibility.Visible)); public Visibility MiddleTbkVisibility { get { return (Visibility)GetValue(MiddleTbkVisibilityProperty); } set { SetValue(MiddleTbkVisibilityProperty, value); } } // Using a DependencyProperty as the backing store for MiddleTbkVisibility. This enables animation, styling, binding, etc... public static readonly DependencyProperty MiddleTbkVisibilityProperty = DependencyProperty.Register("MiddleTbkVisibility", typeof(Visibility), typeof(UCScrollNum), new PropertyMetadata(Visibility.Visible)); public Visibility DownTbkVisibility { get { return (Visibility)GetValue(DownTbkVisibilityProperty); } set { SetValue(DownTbkVisibilityProperty, value); } } // Using a DependencyProperty as the backing store for DownTbkVisibility. This enables animation, styling, binding, etc... public static readonly DependencyProperty DownTbkVisibilityProperty = DependencyProperty.Register("DownTbkVisibility", typeof(Visibility), typeof(UCScrollNum), new PropertyMetadata(Visibility.Visible)); public double UCScrollDuration { get { return (double)GetValue(UCScrollDurationProperty); } set { SetValue(UCScrollDurationProperty, value); } } // Using a DependencyProperty as the backing store for UCScrollDuration. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCScrollDurationProperty = DependencyProperty.Register("UCScrollDuration", typeof(double), typeof(UCScrollNum), new PropertyMetadata(1000.0d)); public int UCValue { get { return (int)GetValue(UCValueProperty); } set { SetValue(UCValueProperty, value); } } // Using a DependencyProperty as the backing store for UCValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCValueProperty = DependencyProperty.Register("UCValue", typeof(int), typeof(UCScrollNum), new PropertyMetadata(0, OnUCValueChanged)); private static void OnUCValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ucScrollNum = d as UCScrollNum; int newValue = 0; if (ucScrollNum != null && Int32.TryParse(e.NewValue?.ToString(), out newValue)) { ucScrollNum.NumValue = newValue; } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propName = "") { var handler = PropertyChanged; if (handler != null) { handler?.Invoke(this, new PropertyChangedEventArgs(propName)); } } private int numValue = 0; public int NumValue { get { return numValue; } set { if (numValue != value) { numValue = value; OnPropertyChanged(nameof(NumValue)); OnUCValueChanged(); } } } private void OnUCValueChanged() { int value = NumValue; int oldValue = value; if (++value > 9) { value = 0; } int nextValue = value + 1; if (nextValue > 9) { nextValue = 0; } AnimateChange(oldValue, value, nextValue, 30, -30, UCScrollDuration); } private void AnimateChange(int oldValue, int nowValue, int nextValue, int fromValue = 0, int toValue = 0, double durationValue = 1000) { Application.Current?.Dispatcher.BeginInvoke(new Action(() => { numTbk1.Text = oldValue.ToString(); numTbk2.Text = nowValue.ToString(); numTbk3.Text = nextValue.ToString(); var animation = new DoubleAnimation { From = fromValue, To = toValue, Duration = TimeSpan.FromMilliseconds(durationValue) }; // Apply animation var transform = new TranslateTransform(); numTbk1.RenderTransform = transform; numTbk2.RenderTransform = transform; numTbk3.RenderTransform = transform; transform.BeginAnimation(TranslateTransform.YProperty, animation); })); } } } //window.xaml <Window x:Class="WpfApp201.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp201" mc:Ignorable="d" xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors" Title="MainWindow" Height="380" Width="200"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <local:UCScrollNum Grid.Row="1" HorizontalAlignment="Center" UCValue="{Binding DataContext.NumValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/> </Grid> </Window> //window.xaml.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp201 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var vm = new MainVM(); this.DataContext = vm; } } public class MainVM : INotifyPropertyChanged { private System.Timers.Timer tmr; public MainVM() { InitTmr(); } private void InitTmr() { if(tmr==null) { tmr= new System.Timers.Timer(); tmr.Interval = 1000; tmr.Elapsed += Tmr_Elapsed; tmr.Start(); } } private void Tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { //++Num; ++NumValue; } private ICommand mouseDownCommand; public ICommand MouseDownCommand { get { if(mouseDownCommand == null) { mouseDownCommand = new DelCommand(MouseDownCommandExecuted, MouseDownCommandCanExecute); } return mouseDownCommand; } } private bool MouseDownCommandCanExecute(object obj) { return true; } private void MouseDownCommandExecuted(object obj) { IsValueIncremented = !IsValueIncremented; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } private int numValue; public int NumValue { get { return numValue; } set { if(value!=numValue) { if(value>9) { value = 0; } if(value<0) { value = 9; } numValue = value; OnPropertyChanged(nameof(NumValue)); } } } private int num=60; public int Num { get { return num; } set { if(value!=num) { num = value; OnPropertyChanged(nameof(Num)); OnNumChanged(); } } } private void OnNumChanged() { var tempNum = Num; HundredsNum = tempNum / 100; TensNum = tempNum % 100 / 10; UIntsNum= tempNum % 10; Console.WriteLine($"Num:{Num},HundredsNum:{HundredsNum},TensNum:{TensNum},UIntsNum:{UIntsNum}"); } private int hundredsNum; public int HundredsNum { get { return hundredsNum; } set { if (value != hundredsNum) { hundredsNum = value; OnPropertyChanged(nameof(HundredsNum)); } } } private int tensNum; public int TensNum { get { return tensNum; } set { if (value != tensNum) { tensNum = value; OnPropertyChanged(nameof(TensNum)); } } } private int uIntsNum; public int UIntsNum { get { return uIntsNum; } set { if (value != uIntsNum) { uIntsNum = value; OnPropertyChanged(nameof(UIntsNum)); } } } private bool isValueIncremented = false; public bool IsValueIncremented { get { return isValueIncremented; } set { if (value != isValueIncremented) { isValueIncremented = value; OnPropertyChanged(nameof(IsValueIncremented)); } } } public class DelCommand : ICommand { private Action<object> execute; private Predicate<object> canExecute; public DelCommand(Action<object> executeValue, Predicate<object> canExecuteValue) { execute = executeValue; canExecute = canExecuteValue; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { if (canExecute == null) { return true; } return canExecute(parameter); } public void Execute(object parameter) { execute(parameter); } } } }