IMI docs

Trace:

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
mvvm [2019/01/11 09:13]
yura
mvvm [2019/01/13 12:01] (current)
yura
Line 1: Line 1:
-**''​MVVM Pattern - Реалізація патерна''​**+**''​MVVM Pattern - Реалізація патерна''​** ​
 ---- ----
 **Лейбли** and **Binding** в XAML  __(в XAML забіндити можна все що завгодно!)__ **Лейбли** and **Binding** в XAML  __(в XAML забіндити можна все що завгодно!)__
 +<​Code:​csharp>​
 +Foreground="​Red" ​                                            ​Міняє колір вмісту
 +FontSize="​50" ​                                               Величена вмісту
 +FontFamily="​Segoe UI" ​                                       Які шрифти будуть використані
 +HorizontalContentAlignment="​Center" ​                         Вірівнення по ширині
 +VerticalContentAlignment="​Center" ​                           Вірівнення по висоті
 +Margin="​0,​ 0, 0, -200" ​                                      ​Зсунути в низ на 200 px
 +Content="​{Binding Time}" ​                                    ​Бінд який падає в клас StopwatchViewModel : INotifyPropertyChanged
 +Content="​{Binding Time, TargetNullValue='​00.00 UAH'​}" ​       TargetNullValue виводить введений текст зразу на екран (в деф позицію)
  
-<​Code:​csharp>​ +Command="{Binding StartStopwatch}" ​                          Біндить ​якусь дію (в нашому випадку це кнопка) 
-Foreground="Red" ​                        Міняє колір вмісту +</​Code> ​ 
-FontSize="​50" ​                           Величена вмісту +
-FontFamily="​Segoe UI" ​                   Які шрифти будуть ​використані +
-Content="​{Binding Time}" ​                ​Бінд який ​падає в клас StopwatchViewModel ​ з інтерфейсом ​ INotifyPropertyChanged +
-HorizontalContentAlignment="​Center" ​     Вірівнення по ширині +
-VerticalContentAlignment="​Center" ​       Вірівнення ​по висоті +
-</​Code>​+
 <​Code:​xaml>​ <​Code:​xaml>​
 <Label Content="​{Binding Time}" Foreground="​Red"​ FontFamily="​Segoe UI" FontSize="​50"​ VerticalContentAlignment="​Center"​ ></​Label>​ <Label Content="​{Binding Time}" Foreground="​Red"​ FontFamily="​Segoe UI" FontSize="​50"​ VerticalContentAlignment="​Center"​ ></​Label>​
 <Label Margin="​{Binding Xyi}" ​ FontFamily="​Segoe UI" FontSize="​50"​ HorizontalContentAlignment="​Center"></​Label>​ <Label Margin="​{Binding Xyi}" ​ FontFamily="​Segoe UI" FontSize="​50"​ HorizontalContentAlignment="​Center"></​Label>​
 </​Code>​ </​Code>​
 +
 +
 ---- ----
 **xaml.cs** __(грубо кажучи це просто main метод!)__ **xaml.cs** __(грубо кажучи це просто main метод!)__
-  * Метод по дефу, потрібен для виклику (НЕ РЕАЛІЗАЦІЇ) реалізовуючих класів +
-  * DataContext потрібен для того щоб достукатись до МОДЕЛЕЙ класу StopwatchViewModel з інтерфейсом ​ INotifyPropertyChanged (Дефолтна штука, якось працює під капотом) +
-  * timer реалізовує TimerMonitore який приймає конструктор класу StopwatchViewModel +
-    * При виклику timer.startstopWatch();​ запускає DispatcherTimer ​ і Stopwatch ​ (тому що в конструкторі НЕ ПРИПУСТИМО робити запуск програми)+
 <​Code:​csharp>​ <​Code:​csharp>​
 namespace CounterSalary namespace CounterSalary
Line 37: Line 39:
 } }
 </​Code>​ </​Code>​
 +
 +  * Любі класи в XAML використовується тільки для виклику **(НЕ РЕАЛІЗАЦІЇ ЛОГІКИ)**
 +  * DataContext потрібен для того щоб достукатись до МОДЕЛЕЙ класу StopwatchViewModel з інтерфейсом ​ INotifyPropertyChanged (Дефолтна штука, якось працює під капотом)
 +  * timer реалізовує TimerMonitor який приймає конструктор класу StopwatchViewModel
 +    * При виклику timer.startstopWatch();​ запускає DispatcherTimer ​ і Stopwatch ​ (тому що в конструкторі НЕ ПРИПУСТИМО робити запуск програми)
 +
 +----
 +**Бінд кнопки виглядає наступним чином**
 +<​Code:​csharp>​
 +<Button Content="​Click"​ Command="​{Binding StartStopwatch}"​ Width="​100"​ Height="​25"​ HorizontalContentAlignment="​Center"​ Margin="​0,​ 0, 0, -200"></​Button>​
 +</​Code>​
 +
 +
 +**Реалізація класу ButtonCommand через інтерфейс ICommand**
 +<​Code:​csharp>​
 +namespace CounterSalary.ViewModel
 +{
 +    public class ButtonCommand : ICommand
 +    {
 +        private readonly Action action;
 +        public event EventHandler CanExecuteChanged;​
 +
 +        public ButtonCommand(Action action)
 +        {
 +            this.action = action;
 +        }
 +
 +        public bool CanExecute(object parameter)
 +        {
 +            return true;
 +        }
 +
 +        public void Execute(object parameter)
 +        {
 +            action();
 +        }
 +    }
 +}
 +
 +</​Code>​
 +**Робиться для того щоб потім можна було його реалізувати через моделі** 👇👇👇
 +<​Code:​csharp>​
 +        public ButtonCommand StartStopwatch { get; set; } = new ButtonCommand(() =>
 +        {
 +            _timer.startStopwatch();​
 +        });
 +</​Code>​
 +----
 +**Даємо івенти на nameof** - будь це хоч Margin хоч Context __(Це один з методів реалізування Біндінгів)__
 +<​Code:​csharp>​
 +delegate { } - пустая функция,​ але може бути і не пустою,​ завдяки неї з варки мажна зробити метод
 +</​Code>​
 +<​Code:​csharp>​
 +namespace CounterSalary.ViewModel
 +{
 +     ​public class StopwatchViewModel : INotifyPropertyChanged
 +    {
 +        public event PropertyChangedEventHandler PropertyChanged=delegate { };
 +        string _count;
 +        string _count1;
 +
 +        public string Time {
 +            get { return _count; }
 +            set { _count = value;
 +                PropertyChanged(this,​ new PropertyChangedEventArgs(nameof(Time)));​
 +            }
 +        }
 +
 +        public string Xyi {
 +            get { return _count1; }
 +            set { _count1 = value;
 +                PropertyChanged(this,​ new PropertyChangedEventArgs(nameof(Xyi)));​
 +            }
 +        }
 +    }
 +}
 +</​Code>​
 +
 +Якщо ви імплементуєте інтерфейс **INotifyPropertyChanged**,​ то ви маєте реалізувати **event PropertyChanged**,​ і відправити його кожен раз, коли значення міняється.
 +
 +----
 +**Рівень сервісу** __(потрібен для реалізації логіки)__
 +<​Code:​csharp>​
 +namespace CounterSalary.Service
 +{
 +    public class TimerMonitore
 +    {
 +        private Stopwatch stopWatch = new Stopwatch();​
 +        private DispatcherTimer dt = new DispatcherTimer();​
 +        private TimeSpan ts;
 +        private StopwatchViewModel _model;
 +        ​
 +        public TimerMonitore(StopwatchViewModel model)
 +        {
 +            dt.Tick += new EventHandler(dtTicker); ​
 +            _model = model;
 +        }
 +
 +        private void dtTicker(object sender, EventArgs e)
 +        {
 +            ts = stopWatch.Elapsed;​
 +            string currentTime = String.Format("​{0:​00}.{1:​00}",​ ts.TotalSeconds,​ ts.Milliseconds / 10);
 +            _model.Time = currentTime;​
 +            _model.Xyi="​400";​
 +        }
 +
 +        public void startstopWatch()
 +        {
 +            dt.Start();
 +            stopWatch.Start();​
 +        }
 +    }
 +}
 +</​Code>​
 +
 +
 +Цей клас **реалізовує логіку** таймера,​ а саме
 +В конструкторі створюється івент на таймер
 +_model.Time = currentTime Заходить в INotifyPropertyChanged і сетить нове значення рівне currentTime - і таким чином в лейблі міняється значення
 +
 +
 +**Пояснення коду нище!**👇
 +
 +<​Code:​csharp>​
 +DispatcherTimer dt = new DispatcherTimer();​ //​Створення нового екземпляра DispatcherTimer ​
 +dt.Interval = TimeSpan.FromSeconds(1);​ //Буде використовувати івент який нище прив*язаний 1 раз в секунду
 +
 +dt.Tick += dtTicker; //​Підписатись на івент
 +dt.Tick -= dtTicker; ​ //​Відписатись від івенту
 +dt.Tick += new EventHandler(dtTicker);​ //​Ідентичний пропис
 +
 +dt.Start(); //​Стартує івент в багатопоточносі ​
 +stopWatch.Start();​ //​Стартує раніше обявлений Stopwatch (Секундомір)
 +
 +private Stopwatch stopWatch = new Stopwatch();​ //​Створює новий екземпляр секундоміра
 +TimeSpan ts = stopWatch.Elapsed;​ //​Cтворює секундомір
 +
 +//0:ХХ Підписатись на перший івент - ts.TotalSeconds
 +//1:ХХ Підписатись на перший івент - ts.Milliseconds ​
 +//​ts.TotalSeconds Абсолютний час - іде дальше чим 60 секунд
 +//​ts.Seconds - на 60 секунді скидується до 0
 +string currentTime = String.Format("​{0:​00}.{1:​00}",​ ts.TotalSeconds,​ ts.Milliseconds / 10);
 +</​Code>​
 +