
рдЖрдЬ
.NET рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдЙрдкрдХрд░рдг рд╣реИ - рдЗрд╕рдХреА рдорджрдж рд╕реЗ рдЖрдк рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рдВрдбреЛрдЬ, рд▓рд┐рдирдХреНрд╕, рдореИрдХрдУрдПрд╕, рдПрдВрдбреНрд░реЙрдЗрдб рдФрд░ рдЖрдИрдУрдПрд╕ рдЬреИрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рд╡рд┐рдХрд╛рд╕ рд╢рд╛рдорд┐рд▓ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо MVVM рдбрд┐рдЬрд╝рд╛рдЗрди рдкреИрдЯрд░реНрди рдФрд░
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред рд╣рдо
ReactiveUI рдФрд░
Fody рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд
рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ, рдЬрд╛рдиреЗрдВ рдХрд┐ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдП,
AvaloniaUI ,
Xamarin Forms ,
Universal Windows Platform ,
Windows Server Foundation рдФрд░
.NET Standard рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ
рдЫреВрдПрдВ , рдФрд░ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯрд┐рдВрдЧ рдореЙрдбрд▓ рд▓реЗрдпрд░реНрд╕ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдкреНрд░рднрд╛рд╡реА рдЯреВрд▓ рд╕реАрдЦреЗрдВред
рд╕рд╛рдордЧреНрд░реА "рдордзреНрдпрдо
рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдо рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ MVVM "
.NET рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрдХреВрд▓рди рд╣реИ рдФрд░ "
рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET рдРрдк рд╡рд╛рдпрд╛ рд░рд┐рдПрдХреНрдЯрд┐рд╡ рдПрдорд╡реАрд╡реАрдПрдо рджреГрд╖реНрдЯрд┐рдХреЛрдг ", рд▓реЗрдЦрдХ рджреНрд╡рд╛рд░рд╛ рдкрд╣рд▓реЗ рдорд╛рдзреНрдпрдо рд╕рдВрд╕рд╛рдзрди рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдирдореВрдирд╛ рдХреЛрдб
GitHub рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ ред
рдкрд░рд┐рдЪрдпред MVVM рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдФрд░ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET
.NET рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкрд░ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдкреЛрд░реНрдЯреЗрдмрд▓ рдФрд░ рд╕рдорд░реНрдерд┐рдд рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдпрджрд┐ рдЖрдк UAMP, WPF, Xamarin Forms рдФрд░ AvaloniaUI рдЬреИрд╕реА XAML рдмреЛрд▓рд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪреМрдЦрдЯреЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ MVVM рдбрд┐рдЬрд╝рд╛рдЗрди рдкреИрдЯрд░реНрди, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдФрд░ .NET рдорд╛рдирдХ рдХреЛрдб рд░рдгрдиреАрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рд╡рд┐рднрд┐рдиреНрди рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдПрдХ рдХреЙрдорди рдХреЛрдб рдмреЗрд╕ рдФрд░ рдХреЙрдорди рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдХрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреЛрд░реНрдЯреЗрдмрд┐рд▓рд┐рдЯреА рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рддрд╛ рд╣реИред
рд╣рдо MVVM рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ - рдореЙрдбрд▓, рджреГрд╢реНрдп рдФрд░ ViewModel рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдирд┐рд░реНрдорд┐рдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рдкреНрд░рддреНрдпреЗрдХ рдкрд░рдд рдкрд░ рдПрдХ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВрдЧреЗред рдореЙрдбрд▓ рдкрд░рдд рдбреЛрдореЗрди рд╕реЗрд╡рд╛рдУрдВ, рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕, рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдВрд╕реНрдерд╛рдУрдВ, рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА - рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд╕рднреА рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИред рджреГрд╢реНрдп рд╕реНрдХреНрд░реАрди рдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрддреНрд╡реЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ рдФрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рджреЛ рдкрд░рддреЛрдВ рдХреЛ рдорд╛рдирд╡ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЙрдбрд▓ рдкрд░рдд рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
MVVM рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рддреАрди рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдкрд░рддреЛрдВ рдХреЗ рдмреАрдЪ рдЬрд┐рдореНрдореЗрджрд╛рд░рд┐рдпреЛрдВ рдХреЗ рд╡рд┐рднрд╛рдЬрди рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрди рдкрд░рддреЛрдВ рдХреЛ .NET рдорд╛рдирдХ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрд╕реЗрдВрдмрд▓реА рдореЗрдВ рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдФрдкрдЪрд╛рд░рд┐рдХ .NET рдорд╛рдирдХ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдкреЛрд░реНрдЯреЗрдмрд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдХрд┐ рдПрдкреАрдЖрдИ рдХреЗ рдПрдХрд▓ рдПрдХреАрдХреГрдд рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рд╡рд┐рднрд┐рдиреНрди .NET рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдорд╡реАрд╡реАрдПрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдФрд░ .NET рд╕реНрдЯреИрдВрдбрд░реНрдб рдХреЛрдб рд╕реЗрдкрд░реЗрд╢рди рд╕реНрдЯреНрд░реИрдЯреЗрдЬреА рдХреЗ рдмрд╛рдж, рд╣рдо рд╡рд┐рднрд┐рдиреНрди рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдФрд░ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рддреИрдпрд╛рд░ рдореЙрдбрд▓ рд▓реЗрдпрд░реНрд╕ рдФрд░ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдкрд╛рдПрдВрдЧреЗред

рдЕрдЧрд░ рд╣рдордиреЗ рд╡рд┐рдВрдбреЛрдЬ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдлрд╝рд╛рдЙрдВрдбреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╡рд┐рдВрдбреЛрдЬ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡реЗрджрди рд▓рд┐рдЦрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдЕрдиреНрдп рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдпреВрдЖрдИ рдпрд╛ рдЬрд╝рдорд╛рд░рд┐рди рдлреЙрд░реНрдореНрд╕ - рдФрд░ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЖрдИрдУрдПрд╕, рдПрдВрдбреНрд░реЙрдЗрдб рдЬреИрд╕реЗ рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдкрд░ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рд▓рд┐рдирдХреНрд╕, OSX, рдФрд░ рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рд╣реЛрдЧреА рдЬрд┐рд╕реЗ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред
рдкрд╛рд░рдВрдкрд░рд┐рдХ MVVM рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рдЧреБрдг рдФрд░ рдЖрджреЗрд╢ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреЗ рд╣реИрдВ рдЬрд┐рдирд╕реЗ XAML рдорд╛рд░реНрдХрдЕрдк рддрддреНрд╡ рдмрд╛рдзреНрдп рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдбреЗрдЯрд╛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ рдХреЛрдИ рднреА рдЧреБрдг рдмрджрд▓рдиреЗ рдкрд░ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ PropertyChanged рдШрдЯрдирд╛ рдХреЛ рдкреЛрд╕реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:
public class ViewModel : INotifyPropertyChanged { public ViewModel() => Clear = new Command(() => Name = string.Empty); public ICommand Clear { get; } public string Greeting => $"Hello, {Name}!"; private string name = string.Empty; public string Name { get => name; set { if (name == value) return; name = value; OnPropertyChanged(nameof(Name)); OnPropertyChanged(nameof(Greeting)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } }
XAML рдпреВрдЖрдИ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реБрдП:
<StackPanel> <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Text="{Binding Greeting, Mode=OneWay}"/> <Button Content="Clear" Command="{Binding Clear}"/> </StackPanel>
рдФрд░ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ! рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЯреЗрдХреНрд╕реНрдЯ рдмреЙрдХреНрд╕ рдореЗрдВ рдЕрдкрдирд╛ рдирд╛рдо рджрд░реНрдЬ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдиреАрдЪреЗ рджрд┐рдпрд╛ рдЧрдпрд╛ рдЯреЗрдХреНрд╕реНрдЯ рддреБрд░рдВрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдмрдзрд╛рдИ рджреЗрддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдПрдХ рдкрд▓ рд░реБрдХрд┐рдП! рд╣рдорд╛рд░реЗ рдпреВрдЖрдИ рдХреЛ рдХреЗрд╡рд▓ рджреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд┐рдП рдЧрдП рдЧреБрдгреЛрдВ рдФрд░ рдПрдХ рдХрдорд╛рдВрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╣рдореЗрдВ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреА рдмреАрд╕ рд╕реЗ рдЕрдзрд┐рдХ рд▓рд╛рдЗрдиреЗрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ? рдпрджрд┐ рд╣рдо рдЕрдзрд┐рдХ рдЧреБрдгреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ рдЬреЛ рд╣рдорд╛рд░реЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ? рдХреЛрдб рдмрдбрд╝рд╛ рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдХреЛрдб рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдФрд░ рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдФрд░ рд╣рдореЗрдВ рдЕрднреА рднреА рдЙрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рд╣реИ!
рдиреБрд╕реНрдЦрд╛ # 1ред рдкреНрд░реЗрдХреНрд╖рдХ рдХрд╛ рдЦрд╛рдХрд╛ред рдЫреЛрдЯреЗ рдЧреЗрдЯрд░реНрд╕ рдФрд░ рд╕реЗрдЯрд░ред ReactiveUI
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рдХреНрд░рд┐рдпрд╛ рдФрд░ рднреНрд░рд╛рдордХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╕рдорд╕реНрдпрд╛ рдирдИ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдХрдИ рд╕рдорд╛рдзрд╛рди рд╣реИрдВред рдкрд╣рд▓реА рдмрд╛рдд рдЖрдкрдХреЛ
рд░рд┐рдПрдХреНрдЯрд┐рд╡рдпреВрдЖрдИ рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо, рдХрд╛рд░реНрдпрд╛рддреНрдордХ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ MVVM рдлреНрд░реЗрдорд╡рд░реНрдХ рд╣реИ рдЬреЛ .NET рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдорд╛рдирдХ .NET рд▓рд╛рдЗрдмреНрд░реЗрд░реА - IObserver рдФрд░ IObservable рдХреЗ рдЗрдВрдЯрд░рдлреЗрд╕ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдСрдмреНрдЬрд░реНрд╡рд░ рдбрд┐рдЬрд╝рд╛рдЗрди рдкреИрдЯрд░реНрди рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдкрдЪрд╛рд╕ рд╕реЗ рдЕрдзрд┐рдХ рдСрдкрд░реЗрдЯрд░ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ
LINQ рд╕рдВрд░рдЪрд┐рдд рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ рдХреЗ рд╕рдорд╛рди рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдИрд╡реЗрдВрдЯ рдлрд╝реНрд▓реЛ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ, рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ, рдЙрдиреНрд╣реЗрдВ рд╕рдореВрд╣рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред рдЬреЗрдЯ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
рдпрд╣рд╛рдБ рдФрд░ рдкрдврд╝реЗрдВред
ReactiveUI рдПрдХ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рднреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ INotifyPropertyChanged - ReactiveObject рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЖрдЗрдП рдлреНрд░реЗрдорд╡рд░реНрдХ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдорд╛рд░реЗ рдирдореВрдирд╛ рдХреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВред
public class ReactiveViewModel : ReactiveObject { public ReactiveViewModel() { Clear = ReactiveCommand.Create(() => Name = string.Empty); this.WhenAnyValue(x => x.Name) .Select(name => $"Hello, {name}!") .ToProperty(this, x => x.Greeting, out greeting); } public ReactiveCommand Clear { get; } private ObservableAsPropertyHelper<string> greeting; public string Greeting => greeting.Value; private string name = string.Empty; public string Name { get => name; set => this.RaiseAndSetIfChanged(ref name, value); } }
рдЗрд╕ рддрд░рд╣ рдХрд╛ рдПрдХ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореЙрдбрд▓ рдкрд┐рдЫрд▓реЗ рд╡рд╛рд▓реЗ рдХреА рддрд░рд╣ рд╣реА рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдХреЛрдб рдЫреЛрдЯрд╛ рд╣реЛрддрд╛ рд╣реИ, рдпрд╣ рдЕрдзрд┐рдХ рдкреНрд░реЗрдбрд┐рдХреНрдЯреЗрдмрд▓ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореЙрдбрд▓ рдХреЗ рдкреНрд░реЙрдкрд░реНрдЯреАрдЬ рдХреЗ рдмреАрдЪ рдХреЗ рд╕рднреА рд░рд┐рд▓реЗрд╢рдирд╢рд┐рдкреНрд╕ рдХреЛ рдПрдХ рдЬрдЧрд╣ рдкрд░
LINQ рд╕реЗ рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдмреЗрд╢рдХ, рд╣рдо рдпрд╣рд╛рдВ рд░реБрдХ рд╕рдХрддреЗ рдереЗ, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдХрд╛рдлреА рдХреЛрдб рд╣реИ - рд╣рдореЗрдВ рдЧреЗрдЯрд░реНрд╕, рд╕реЗрдЯрд░рд░реНрд╕ рдФрд░ рдлреАрд▓реНрдбреНрд╕ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдиреБрд╕реНрдЦрд╛ # 2ред рдЗрдирдХреИрдкреНрд╕реБрд▓реЗрд╢рди INotifyPropertyChangedред ReactiveProperty
рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рдорд╛рдзрд╛рди
ReactiveProperty рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдЬреЛ рд░реИрдкрд░ рдХрдХреНрд╖рд╛рдПрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╕реВрдЪрдирд╛рдПрдВ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИрдВред
ReactiveProperty рдХреЗ рд╕рд╛рде
, рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рдХрд┐рд╕реА рднреА рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдкрддреНрддрд┐ INotifyPropertyChanged рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИред рдРрд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдЧреБрдг IObservable рдХреЛ рднреА рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдо рдЙрдирдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдХрд┐ рд╣рдо
ReactiveUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рдереЗред ReactiveProperty рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдорд╛рд░реЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рдмрджрд▓реЗрдВред
public class ReactivePropertyViewModel { public ReadOnlyReactiveProperty<string> Greeting { get; } public ReactiveProperty<string> Name { get; } public ReactiveCommand Clear { get; } public ReactivePropertyViewModel() { Clear = new ReactiveCommand(); Name = new ReactiveProperty<string>(string.Empty); Clear.Subscribe(() => Name.Value = string.Empty); Greeting = Name .Select(name => $"Hello, {name}!") .ToReadOnlyReactiveProperty(); } }
рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдЧреБрдгреЛрдВ рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЙрдирдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдз рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдкреНрд░реЙрдкрд░реНрдЯреА рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рднреА рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдЦрд╛рдореА рд╣реИ - рд╣рдореЗрдВ рдЕрдкрдирд╛ XAML рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ рддрд╛рдХрд┐ рдбреЗрдЯрд╛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛рдо рдХрд░ рд╕рдХреЗред рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдЧреБрдг рд░реИрдкрд░ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпреВрдЖрдИ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдРрд╕реЗ рд░реИрдкрд░ рдХреА рдЕрдкрдиреА рд╕рдВрдкрддреНрддрд┐ рд╕реЗ рдмрдВрдзрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП!
<StackPanel> <TextBox Text="{Binding Name.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Text="{Binding Greeting.Value, Mode=OneWay}"/> <Button Content="Clear" Command="{Binding Clear}"/> </StackPanel>
рдиреБрд╕реНрдЦрд╛ # 3ред рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдмрджрд▓рдирд╛ред рдкреНрд░реЙрдкрд░реНрдЯреАрдЪреЗрдВрдбреЗ.рдлреЛрдбреА + рд░рд┐рдПрдХреНрдЯрд┐рд╡рд┐рд╡рдпреВ
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рд╕реВрдЪрдирд╛рдПрдВ рднреЗрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм рдЗрд╕рдХрд╛ рдореВрд▓реНрдп рдмрджрд▓рддрд╛ рд╣реИред
PropertyChanged.Fody рдХреЗ рд╕рд╛рде, рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИред рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рд╡рд╣ рд╣реИ
AddinotifyPropertyChangedInterface рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рд╡реНрдпреВ рдореЙрдбрд▓ рд╡рд░реНрдЧ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП - рдФрд░ рдкреНрд░реЙрдкрд░реНрдЯреАрдЪреЗрдВрдЬ рдИрд╡реЗрдВрдЯ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдХреЛрдб
INOTifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдирд┐рд░реНрдорд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж
рдмрд╕рдиреЗ рд╡рд╛рд▓реЛрдВ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛, рдпрджрд┐ рдХреЛрдИ рдЧрд╛рдпрдм рд╣реИред рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рд╣рдорд╛рд░реЗ рдЧреБрдгреЛрдВ рдХреЛ рдмрджрд▓рддреЗ рдореВрд▓реНрдпреЛрдВ рдХреА рдзрд╛рд░рд╛рдУрдВ рдореЗрдВ рдмрджрд▓ рджреЗрдВ, рд╣рдо рд╣рдореЗрд╢рд╛
ReactiveUI рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ
рд╡реНрд╣реЗрдирдПрд╡рд▓реНрдпреВ рдПрдХреНрд╕рдЯреЗрдВрд╢рди
рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рддреАрд╕рд░реА рдмрд╛рд░ рд╣рдорд╛рд░реЗ рдирдореВрдиреЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВ, рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдХрд┐рддрдирд╛ рдЕрдзрд┐рдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╣реЛрдЧрд╛!
[AddINotifyPropertyChangedInterface] public class FodyReactiveViewModel { public ReactiveCommand Clear { get; } public string Greeting { get; private set; } public string Name { get; set; } = string.Empty; public FodyReactiveViewModel() { Clear = ReactiveCommand.Create(() => Name = string.Empty); this.WhenAnyValue(x => x.Name) .Select(name => $"Hello, {name}!") .Subscribe(x => Greeting = x); } }
Fody рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ IL рдХреЛрдб рдХреЛ рдмрджрд▓рддрд╛ рд╣реИред
AddCotifyPropertyChangedInterface рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдпрд╛
INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдпрд╛ рдРрд╕реА рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ
рдмрд╕рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЛ
рд╕рдореНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЖрдк рдЕрдзрд┐рдХ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдб рдкреАрдврд╝реА рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ рдФрд░ рдЖрдВрджреНрд░реЗрдИ рдХреБрд░реЛрд╢ рдХреА рд░рд┐рдкреЛрд░реНрдЯ "
рд░рд┐рдлреНрд▓реЗрдХреНрдЯ.рдЗрдорд┐рдЯред рдкреНрд░реИрдХреНрдЯрд┐рд╕ рдСрдл рдпреВрдЬ " рд╕реЗ рдЗрд╕реЗ рдФрд░ рдХрд┐рди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╣рд╛рд▓рд╛рдБрдХрд┐ PropertyChanged.Fody рд╣рдореЗрдВ рд╕реНрд╡рдЪреНрдЫ рдФрд░ рдЕрд░реНрдердкреВрд░реНрдг рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред 4.5 рдлреНрд░реЗрдорд╡рд░реНрдХ рд╕рд╣рд┐рдд .NET рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреА рд╡рд┐рд░рд╛рд╕рдд рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рдмрд╛рдж рдореЗрдВ, рдЕрдм рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд░рд┐рдПрдХреНрдЯрд┐рд╡реБрдЗ рдФрд░ рдлреЛрдбреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдкрд░ рдФрд░ рдЗрд╕ рдмрд╛рдд рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдХрд┐ рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдХрднреА рднреА рдареАрдХ рдирд╣реАрдВ рд╣реЛрдВрдЧреА! .NET рдХреЛрд░ рдХреЗ рд▓рд┐рдП рд╕рдВрд╕реНрдХрд░рдг
Microsoft рд╕рдорд░реНрдерди рдиреАрддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВред
рд╕рд┐рджреНрдзрд╛рдВрдд рд╕реЗ рдЕрднреНрдпрд╛рд╕ рддрдХред ReactiveUI рдФрд░ PropertyChanged.Fody рдХреЗ рд╕рд╛рде рдорд╛рдиреНрдп рд░реВрдкреЛрдВ
рдЕрдм рд╣рдо рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред рдЖрдЗрдП рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдо UX рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддреЗ рд╣реБрдП рдПрдХ рдЬрдЯрд┐рд▓ рдмрд╣реБ-рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдгрд╛рд▓реА рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЕрдкрдиреЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдПрдХрддреНрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЬрдм рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдмрдЧ рд░рд┐рдкреЛрд░реНрдЯ рд╣реИ рдпрд╛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕реБрдзрд╛рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕реБрдЭрд╛рд╡ рд╣реИ, рд╣рдо рднреА рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреЛ рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕рдореВрд╣рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рддрдм рддрдХ рдкрддреНрд░ рдирд╣реАрдВ рднреЗрдЬрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм рддрдХ рд╡реЗ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдирд╣реАрдВ рднрд░рддреЗ рд╣реИрдВред рдПрдХ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдЬреЛ рдКрдкрд░ рд╕реВрдЪреАрдмрджреНрдз рд╢рд░реНрддреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:
[AddINotifyPropertyChangedInterface] public sealed class FeedbackViewModel { public ReactiveCommand<Unit, Unit> Submit { get; } public bool HasErrors { get; private set; } public string Title { get; set; } = string.Empty; public int TitleLength => Title.Length; public int TitleLengthMax => 15; public string Message { get; set; } = string.Empty; public int MessageLength => Message.Length; public int MessageLengthMax => 30; public int Section { get; set; } public bool Issue { get; set; } public bool Idea { get; set; } public FeedbackViewModel(IService service) { this.WhenAnyValue(x => x.Idea) .Where(selected => selected) .Subscribe(x => Issue = false); this.WhenAnyValue(x => x.Issue) .Where(selected => selected) .Subscribe(x => Idea = false); var valid = this.WhenAnyValue( x => x.Title, x => x.Message, x => x.Issue, x => x.Idea, x => x.Section, (title, message, issue, idea, section) => !string.IsNullOrWhiteSpace(message) && !string.IsNullOrWhiteSpace(title) && (idea || issue) && section >= 0); valid.Subscribe(x => HasErrors = !x); Submit = ReactiveCommand.Create( () => service.Send(Title, Message), valid ); } }
рд╣рдо
AddinotifyPropertyChangedInterface рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ - рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╕рднреА рдЧреБрдг рдпреВрдЖрдИ рдХреЛ рдЙрдирдХреЗ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреА рд╕реВрдЪрдирд╛ рджреЗрдВрдЧреЗред
WhenAnyValue рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ
рд╣реБрдП , рд╣рдо рдЗрди рдЧреБрдгреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдВрдЧреЗ рдФрд░ рдЕрдиреНрдп рдЧреБрдгреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВрдЧреЗред рдЬрдм рддрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдлрд╝реЙрд░реНрдо рдХреЛ рдкреВрд░рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рддрдм рддрдХ рдлреЙрд░реНрдо рдЬрдорд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдЯреАрдо рдмрдВрдж рд░рд╣реЗрдЧреАред рд╣рдо .NET рдХреЛрдб рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдХреНрд▓рд╛рд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдЕрдкрдирд╛ рдХреЛрдб рд╕рд╣реЗрдЬреЗрдВрдЧреЗ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝реЗрдВрдЧреЗред
рдЗрдХрд╛рдИ рдореЙрдбрд▓ рдкрд░реАрдХреНрд╖рдг
рдкрд░реАрдХреНрд╖рдг рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде, рд╣рдо рдЕрдкрдиреЗ рдХреЛрдб рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рд░реАрдлреИрдХреНрдЯрд░ рдХрд░рдиреЗ рд╕реЗ рдбрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрдВрдЧреЗ - рдЖрдЦрд┐рд░рдХрд╛рд░, рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд╕рд╣реА рд╕рдВрдЪрд╛рд▓рди рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ рдХрд┐ рд╡реЗ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░рд╛ рд╣реЛ рдЧрдП рд╣реИрдВред MVVM рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рддреАрди рдкрд░рддреЗрдВ рд╣реЛрддреА рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рджреЛ рдореЗрдВ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╕реНрд╡рддрдВрддреНрд░ рддрд░реНрдХ рд╣реЛрддреЗ рд╣реИрдВ - рдФрд░ рд╣рдо рдЗрд╕реЗ .NET рдХреЛрд░ рдФрд░
XUnit рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдореЙрдмреНрд╕ рдФрд░
рд╕реНрдЯрдмреНрд╕ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП,
NSubstitute рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ, рдЬреЛ "рдирдХрд▓реА рд╡рд╕реНрддреБрдУрдВ" рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рд╕рд┐рд╕реНрдЯрдо рдПрдХреНрд╢рди рдФрд░ рд╡реИрд▓реНрдпреВрдЬ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдПрдкреАрдЖрдИ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
var sumService = Substitute.For<ISumService>(); sumService.Sum(2, 2).Returns(4);
рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдХреЛрдб рдФрд░ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢реЛрдВ рджреЛрдиреЛрдВ рдХреА рдкрдардиреАрдпрддрд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
рдлреНрд▓реБрдПрдВрдЯрд╕реЙрд░реНрд╕рди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рд╕рд╛рде, рд╣рдореЗрдВ рди рдХреЗрд╡рд▓ рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХреМрди рд╕рд╛ рддрд░реНрдХ Assert.Equal рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдореВрд▓реНрдп рдХреЛ рдЧрд┐рдирддрд╛ рд╣реИ, рдФрд░ рдЬреЛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдореВрд▓реНрдп рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░рд╛ IDE рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦреЗрдЧрд╛!
var fibs = fibService.GetFibs(10); fibs.Should().NotBeEmpty("because we've requested ten fibs"); fibs.First().Should().Be(1);
рдЖрдЗрдП рд╣рдорд╛рд░реЗ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВред
[Fact] public void ShouldValidateFormAndSendFeedback() {
рд╡рд┐рдВрдбреЛрдЬ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдпреВрдЖрдИ
рдареАрдХ рд╣реИ, рдЕрдм рд╣рдорд╛рд░реЗ рдкреНрд░рд╕реНрддреБрддрд┐ рдореЙрдбрд▓ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рд╣рдореЗрдВ рдпрдХреАрди рд╣реИ рдХрд┐ рд╕рдм рдХреБрдЫ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреА рдкреНрд░рд╕реНрддреБрддрд┐ рдкрд░рдд рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ - рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рдирд┐рд░реНрднрд░ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рд╡рд┐рдВрдбреЛрдЬ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╕реНрд╡рддрдВрддреНрд░ рддрд░реНрдХ рдпреБрдХреНрдд .NET рд╕реНрдЯреИрдВрдбрд░реНрдб рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рдЕрдЧрд▓рд╛, рдЫреЛрдЯреА рдЪреАрдЬ рдПрдХреНрд╕рдПрдПрдордПрд▓ рдореЗрдВ рдирд┐рдпрдВрддреНрд░рдгреЛрдВ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдирд╛ рд╣реИ, рдЙрдирдХреЗ рдЧреБрдгреЛрдВ рдХреЛ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рдЧреБрдгреЛрдВ рд╕реЗ рдмрд╛рдВрдзрдирд╛ рдФрд░ рдХрд┐рд╕реА рднреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХреЗ
рд╕реЗ рдбреЗрдЯрд╛ рд╕рдВрджрд░реНрдн рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦрдирд╛ рд╣реИред рдЪрд▓реЛ рдпрд╣ рдХрд░рддреЗ рд╣реИрдВ!
<StackPanel Width="300" VerticalAlignment="Center"> <TextBlock Text="Feedback" Style="{StaticResource TitleTextBlockStyle}"/> <TextBox PlaceholderText="Title" MaxLength="{Binding TitleLengthMax}" Text="{Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Style="{StaticResource CaptionTextBlockStyle}"> <Run Text="{Binding TitleLength, Mode=OneWay}"/> <Run Text="letters used from"/> <Run Text="{Binding TitleLengthMax}"/> </TextBlock> <TextBox PlaceholderText="Message" MaxLength="{Binding MessageLengthMax}" Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Style="{StaticResource CaptionTextBlockStyle}"> <Run Text="{Binding MessageLength, Mode=OneWay}"/> <Run Text="letters used from"/> <Run Text="{Binding MessageLengthMax}"/> </TextBlock> <ComboBox SelectedIndex="{Binding Section, Mode=TwoWay}"> <ComboBoxItem Content="User Interface"/> <ComboBoxItem Content="Audio"/> <ComboBoxItem Content="Video"/> <ComboBoxItem Content="Voice"/> </ComboBox> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <CheckBox Grid.Column="0" Content="Idea" IsChecked="{Binding Idea, Mode=TwoWay}"/> <CheckBox Grid.Column="1" Content="Issue" IsChecked="{Binding Issue, Mode=TwoWay}"/> </Grid> <TextBlock Visibility="{Binding HasErrors}" Text="Please, fill in all the form fields." Foreground="{ThemeResource AccentBrush}"/> <Button Content="Send Feedback" Command="{Binding Submit}"/> </StackPanel>
рдЕрдВрдд рдореЗрдВ, рд╣рдорд╛рд░рд╛ рдлреЙрд░реНрдо рддреИрдпрд╛рд░ рд╣реИред

Xamarin.Forms рдХреЗ рд▓рд┐рдП рдпреВрдЖрдИ
Android рдФрд░ iOS рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдореЛрдмрд╛рдЗрд▓ рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдирдпрд╛
Xamarin.Forms рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдореЛрдмрд╛рдЗрд▓ рдбрд┐рд╡рд╛рдЗрд╕реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд Xamarin рдирд┐рдпрдВрддреНрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ
UI рдХрд╛
рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ ред

рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдпреВрдЖрдИ
рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET рдлреНрд░реЗрдорд╡рд░реНрдХ рд╣реИ рдЬреЛ WPF, UWP рдпрд╛ Xamarin.Forms рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдЪрд┐рдд XAML рдмреЛрд▓реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЕрд╡рд▓реЛрдирд┐рдпрд╛ рд╡рд┐рдВрдбреЛрдЬ, рд▓рд┐рдирдХреНрд╕ рдФрд░ рдУрдПрд╕рдПрдХреНрд╕ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ
рдЧреАрдерд╣рдм рдкрд░ рдЙрддреНрд╕рд╛рд╣реА рд▓реЛрдЧреЛрдВ рдХреЗ рд╕рдореБрджрд╛рдп рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛
рд╣реИ ред
ReactiveUI рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
, рдЖрдкрдХреЛ
Avalonia.ReactiveUI рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЕрд╡рд▓реЛрдирд┐рдпрд╛ рдПрдХреНрд╕рдПрдПрдордПрд▓ рдкрд░
рдкреНрд░рд╕реНрддреБрддрд┐ рдкрд░рдд рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ !

рдирд┐рд╖реНрдХрд░реНрд╖
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред 2018 рдореЗрдВ .NET рд╣рдореЗрдВ
рд╕рд╣реА рдорд╛рдпрдиреЗ рдореЗрдВ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ - UWP, Xamarin.Forms, WPF рдФрд░ AvaloniaUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо Android, iOS, Windows, Linux, OSX рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдорд╡реАрд╡реАрдПрдо рдбрд┐рдЬрд╝рд╛рдЗрди рдкреИрдЯрд░реНрди рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдЬрд╝ рдЬреИрд╕реЗ
рд░рд┐рдПрдХреНрдЯрд┐рд╡рдпреВрдЖрдИ рдФрд░
рдлреЛрдбреА рд╕реНрдкрд╖реНрдЯ, рдмрдирд╛рдП рд░рдЦрдиреЗ рдпреЛрдЧреНрдп рдФрд░ рдкреЛрд░реНрдЯреЗрдмрд▓ рдХреЛрдб рд▓рд┐рдЦрдХрд░ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рд░рд▓ рдФрд░ рддреЗрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдб рд╕рдВрдкрд╛рджрдХреЛрдВ рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪрд╛, рд╡рд┐рд╕реНрддреГрдд рджрд╕реНрддрд╛рд╡реЗрдЬ рдФрд░ рдЕрдЪреНрдЫрд╛ рд╕рдорд░реНрдерди .NET рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рдЖрдХрд░реНрд╖рдХ рдмрдирд╛рддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдк .NET рдореЗрдВ рдбреЗрд╕реНрдХрдЯреЙрдк рдпрд╛ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЕрднреА рддрдХ ReactiveUI рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ - рдпрд╣ рдврд╛рдВрдЪрд╛
iOS рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп GitHub рдХреНрд▓рд╛рдЗрдВрдЯреНрд╕ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛
рд╣реИ ,
GitHub рдХреЗ рд▓рд┐рдП рд╡рд┐рдЬреБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди,
Atitian SourceTree git рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░
рд╡рд┐рдВрдбреЛрдЬ 10 рдХреЗ рд▓рд┐рдП рд╕реБрд╕реНрддред рдореЛрдмрд╛рдЗрд▓ ред
Habr├й рдкрд░ ReactiveUI рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓реЗрдЦреЛрдВ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБ рдмрди рд╕рдХрддреА рд╣реИред рдЬрд╝рд╛рдорд╛рд░рд┐рди рдкрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП, рд░рд┐рдПрдХреНрдЯрд┐рд╡реБрдЗ рдХреЗ рд▓реЗрдЦрдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╕реЗ рдХреЛрд░реНрд╕ "
рд╕реА # рдХреЗ рд╕рд╛рде рдПрдХ рдЖрдИрдУрдПрд╕ рдРрдк рдХрд╛ рдирд┐рд░реНрдорд╛рдг " рд╕рдВрднрд╡рддрдГ рдХрд╛рдо рдЖрдПрдЧрд╛ред рдЖрдк
рдПрдЧрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓реЗрдЦ рд╕реЗ рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдкрд░ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЕрдиреБрднрд╡ рдХреЗ
рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ - .NET рдХреЛрд░ рдкрд░ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХреНрд▓рд╛рдЗрдВрдЯред
рд▓реЗрдЦ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕реНрд░реЛрдд рдФрд░ рд░рд┐рдПрдХреНрдЯрд┐рд╡рдпреВрдЖрдИ рдФрд░ рдлреЛрдбреА рдХреЗ рд╕рд╛рде рд╡реИрдз рд░реВрдкреЛрдВ рдХреА рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реБрдП рдЧрд┐рдЯрд╣рдм
рдкрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред рд╡рд┐рдВрдбреЛрдЬ, рд▓рд┐рдирдХреНрд╕, рдореИрдХрдУрдПрд╕ рдФрд░ рдПрдВрдбреНрд░реЙрдЗрдб рдкрд░ рдЪрд▓ рд░рд╣реЗ рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдФрд░ рд░рд┐рдПрдХреНрдЯрд┐рд╡реБрдЗ, рд░рд┐рдПрдХреНрдЯрд┐рд╡рдпреВрдЖрдИ.рдлреЛрдбреА рдФрд░
рдЕрдХрд╛рд╡рд╛рдЪреЗ рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди
рдЬреАрдерд╣рдм рдкрд░ рднреА рдЙрдкрд▓рдмреНрдз рд╣реИ ред