MVVM рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИ


рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐


рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЬреЛ MVVM (рдореЙрдбрд▓ рд╡реНрдпреВ рд╡реНрдпреВ-рдореЙрдбрд▓) рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдПрдХ рд╣реА рддрд░реНрдХ рд╣реИ: WPF, рд╕рд┐рд▓реНрд╡рд░рд▓рд╛рдЗрдЯ, рд╡рд┐рдВрдбреЛрдЬ рдлреЛрдиред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдХрд┐рд╕реА рднреА MVVM рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдкрд╣рд▓реЗ, рдЙрджрд╛рд╣рд░рдг, рдлрд┐рд░ рдбреАрдмреНрд░реАрдлрд┐рдВрдЧред

рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕рднреА рдХреЛрдб рдореЗрд░реЗ рдПрдкреЗрдХреНрд╕ рдПрдорд╡реАрд╡реАрдПрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рднреА рднрд╛рдЧреЛрдВ рдХреЛ рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдЖрдкрдХреЛ рдЗрди рддрд░реАрдХреЛрдВ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдпрд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдпрд╛ рдЖрдк рдмрд╕ рдПрдкреЗрдХреНрд╕ рд▓рд┐рдВрдХ рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рддреБрд░рдВрдд рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЫрд╡рд┐
рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ 1: WPF рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИ

рдЫрд╡рд┐
рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ 2: рд╕рд┐рд▓реНрд╡рд░рд▓рд╛рдЗрдЯ рдореЗрдВ рдЯреАрдореЗрдВ

рдЫрд╡рд┐
рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ 3: рд╡рд┐рдВрдбреЛрдЬ рдлреЛрди рдореЗрдВ рдХрдорд╛рдВрдб рдХрд░рддрд╛ рд╣реИ

рдХреНрдпрд╛ рд╣реИрдВ рдЯреАрдореЗрдВ?

рдХрдорд╛рдВрдб рдЬреБрдбрд╝реА рд╣реБрдИ рд╡рд╕реНрддреБрдПрдВ рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ рддрд░реНрдХ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВред

рдпрджрд┐ рд╣рдо рдЯреАрдореЛрдВ рдкрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╡реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ:

рдЙрджрд╛рд╣рд░рдг

рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдЖрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдХреЛ рдмрд╛рдж рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ред

рдорд╣рддреНрд╡рдкреВрд░реНрдг : рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдЗрд╕ рднрд╛рдЧ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ "рд╕рдВрджреЗрд╢" рдирд╛рдо рдХреЗ рд╕рд╛рде рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рдЕрд╡рд▓реЛрдХрди рдпреЛрдЧреНрдп рд╕рдВрдЧреНрд░рд╣ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ - рдкреНрд░рддреНрдпреЗрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЙрджрд╛рд╣рд░рдг рдПрдХ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрд┐ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред

рджреГрд╢реНрдп рдХреЗ рдореВрд▓ рдореЙрдбрд▓ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ (рджреЗрдЦреЗрдВ рдореЙрдбрд▓):

public class MainViewModel : ViewModel { public MainViewModel() { } private ObservableCollection<string> messages = new ObservableCollection<string>(); public ObservableCollection<string> Messages { get { return messages; } } } 


рдпрд╣ рджреГрд╢реНрдп рдореЙрдбрд▓ ViewModel рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЖрдк рдХрд┐рд╕реА рдЕрдиреНрдп рдЙрдкрд▓рдмреНрдз рдкреНрд░рдХрд╛рд░ рдХреЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг 1 - рдХрдорд╛рдВрдб рдХрд╛ рд╕рд░рд▓ рдЙрдкрдпреЛрдЧ
рдЙрджреНрджреЗрд╢реНрдп : рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рддрддреНрд╡ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВред

рдЕрдм рдЖрдЬреНрдЮрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЙрдбрд▓ рдореЗрдВ рдХрдорд╛рдВрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ - рдПрдХ рд╕рдВрдмрджреНрдз рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕реЗ рдХрдорд╛рдВрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:
 public class MainViewModel : ViewModel { public MainViewModel() { //   -  DoSimpleCommand. simpleCommand = new Command(DoSimpleCommand); } /// <summary> /// The SimpleCommand function. /// </summary> private void DoSimpleCommand() { //   Messages.Add(" 'DoSimpleCommand'."); } /// <summary> ///    /// </summary> private Command simpleCommand; /// <summary> ///    /// </summary> public Command SimpleCommand { get { return simpleCommand; } } } 

рдЕрдм рдмрдЯрди рдирд┐рдпрдВрддреНрд░рдг рдХреЗ "рдХрдорд╛рдВрдб" рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рдПрдХ рдХрдорд╛рдВрдб рдЬреЛрдбрд╝реЗрдВред
 <Button Content="Simple Command" Command="{Binding SimpleCommand}" /> 

рд╡рд╣ рд╕рдм рд╣реИред рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИред рд╣рдордиреЗ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрддреНрд╡ рдХреА рдХрдорд╛рдВрдб рдкреНрд░реЙрдкрд░реНрдЯреА рдкрд░ рдХрдорд╛рдВрдб рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рдВрд▓рдЧреНрди рдХрд┐рдпрд╛ рд╣реИред рдЬрдм рдХреЛрдИ рддрддреНрд╡ рд╕рдХреНрд░рд┐рдп рд╣реЛрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд рдЬрдм рдПрдХ рдмрдЯрди рджрдмрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдХрдорд╛рдВрдб рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЗрд╕реА DoSimpleCommand рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ)ред

рдЙрджрд╛рд╣рд░рдг 2 - рд▓реИрдВрдмрдбрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрдорд╛рдВрдб рдХрд╛ рд╕рд░рд▓ рдЙрдкрдпреЛрдЧ
рдЙрджреНрджреЗрд╢реНрдп : рд╕рдХреНрд░рд┐рдпрдг рдпрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрддреНрд╡ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рджреМрд░рд╛рди рджреГрд╢реНрдп рдореЙрдбрд▓ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдХрд╛рд░реНрдп рд╣реИ, рдЬрд┐рд╕реЗ рдореИрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд╣реАрдВ рд▓рд┐рдЦрдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд▓рдВрдмреЛрджрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред

рдЗрд╕ рдореИрдиреБрдЕрд▓ рдХреЗ рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ, рдЖрдк рдпрд╛ рддреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг 1 рдореЗрдВ, рдпрд╛ рдореЗрдордиреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЬреЛ рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рдХрдо рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдмрдирд╛ рджреЗрдЧрд╛ред рдЪреБрдирд╛рд╡ рдЖрдкрдХрд╛ рд╣реИред
 public MainViewModel() { //      .      . lambdaCommand = new Command( () => { Messages.Add("    .      . "); }); } /// <summary> /// The command object. /// </summary> private Command lambdaCommand; /// <summary> /// Gets the command. /// </summary> public Command LambdaCommand { get { return lambdaCommand; } } 

рдлрд┐рд░ рд╕реЗ, рд╣рдо рдХрдорд╛рдВрдб рдХреЛ рд╣рдорд╛рд░реЗ рдмрдЯрди рдХреА рдХрдорд╛рдВрдб рдкреНрд░реЙрдкрд░реНрдЯреА рд╕реЗ рдмрд╛рдБрдзрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреЛрд╣рд░рд╛рдПрдВрдЧреЗ:
 <Button Content="Lambda Command" Command="{Binding LambdaCommand}" /> 


рдЙрджрд╛рд╣рд░рдг 3 - рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдХрдорд╛рдВрдб рдХрд╛ рд╕рд░рд▓ рдЙрдкрдпреЛрдЧ
рдЙрджреНрджреЗрд╢реНрдп : рдПрдХ рдЯреАрдо рдмрдирд╛рдПрдВ рдЬреЛ рдбреЗрдЯрд╛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдкрд╛рд╕ рдХрд┐рдП рдЧрдП рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдХрдорд╛рдВрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ (рдпрд╣ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕рдХреЙрд╕рдордВрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рджреЗрдЦреЗрдВрдЧреЗ)ред рдкрд╛рд░рд┐рдд рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рддрдерд╛рдХрдерд┐рдд рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
 public class MainViewModel : ViewModel { public MainViewModel() { //    parameterizedCommand = new Command(DoParameterisedCommand); } /// <summary> ///   /// </summary> private void DoParameterisedCommand(object parameter) { Messages.Add("   тАУ  : '" + parameter.ToString() + "'."); } /// <summary> /// The command object. /// </summary> private Command parameterizedCommand; /// <summary> /// Gets the command. /// </summary> public Command ParameterisedCommand { get { return parameterizedCommand; } } } 

рдмрдЯрди рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдХрдорд╛рдВрдб рдХреЗ рдмрдВрдзрди рдХреЛ рджреЛрд╣рд░рд╛рдПрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВ:
 <Button Content="Parameterized Command" Command="{Binding ParameterizedCommand}" CommandParameter={Binding SomeObject} /> 

рдЬрд╣рд╛рдВ рднреА рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрдирдХреЗ рд▓рд┐рдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред рдХрдорд╛рдВрдб рдмрдирд╛рддреЗ рд╕рдордп, рдЖрдк рдПрдХреНрд╢рди (рдмрд┐рдирд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдХрдорд╛рдВрдб рдХрдорд╛рдВрдб) рдпрд╛ рдПрдХреНрд╢рди <рдСрдмреНрдЬреЗрдХреНрдЯ> (рдЯрд╛рдЗрдк рдХрдорд╛рдВрдб рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдХрдорд╛рдВрдб рдлрд╝рдВрдХреНрд╢рди) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реИрдореНрдмреНрдбрд╛ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рднреА рд╣реИ:
 //       parameterizedCommand = new Command( (parameter) => { Messages.Add("   тАУ  : '" + parameter.ToString() + "'."); }); 


рдЙрджрд╛рд╣рд░рдг 4 - рдХрдорд╛рдВрдб рдХреЛ рд╕рдХреНрд╖рдо рдФрд░ рдЕрдХреНрд╖рдо рдХрд░рдирд╛
рд▓рдХреНрд╖реНрдп : рдХреЛрдб рдпрд╛ XAML рд╕реЗ рдХрдорд╛рдВрдб рдХреЛ рд╕рдХреНрд╖рдо / рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝реЗрдВ

рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдВрдб рдореЗрдВ CanExecute рдкреНрд░реЙрдкрд░реНрдЯреА рд╣реЛрддреА рд╣реИ, рдЬреЛ рдХрд┐ рд╕рд╣реА рд╣реЛрдиреЗ рдкрд░, рдХрдорд╛рдВрдб рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рддреА рд╣реИ, рдФрд░ рдЬрдм рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рд╣реЛрддреА рд╣реИ, рддреЛ рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХрд░ рджреЗрддреА рд╣реИ, рд╕рд╛рде рд╣реА рд╕рдВрдмрдВрдзрд┐рдд рдирд┐рдпрдВрддреНрд░рдг рдХреЛ рднреАред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЬрдм рдХрдорд╛рдВрдб рдХреЛ рдЕрдХреНрд╖рдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рдмрдЯрди рднреА рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ:
 public class MainViewModel : ViewModel { public MainViewModel() { //  /  enableDisableCommand = new Command( () => { Messages.Add("/ ."); }, false); } private void DisableCommand() { //   EnableDisableCommand.CanExecute = false; } private void EnableCommand() { //   EnableDisableCommand.CanExecute = true; } /// <summary> /// The command object. /// </summary> private Command enableDisableCommand; /// <summary> /// Gets the command. /// </summary> public Command EnableDisableCommand { get { return enableDisableCommand; } } } 

рд╣рдо рдмрдЯрди (рдпрд╛ рдЕрдиреНрдп рддрддреНрд╡) рдХреЗ рд▓рд┐рдП рдПрдХ рдмрдВрдзрди рдмрдирд╛рддреЗ рд╣реИрдВ:
 <Button Content="Enable/Disable Command" Command="{Binding EnableDisableCommand}" /> 

рдпрд╣ CanExecute рдХрдорд╛рдВрдб рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдмрд╛рдВрдзрдиреЗ рдХреЗ рд▓рд┐рдП рднреА рд╕рдВрднрд╡ рд╣реИред
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдХреЛрдб рдореЗрдВ рдХрдорд╛рдВрдб рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, CanExecute рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рдорд╛рди рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВред рдФрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ (XAML) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЪреЗрдХрдмреЙрдХреНрд╕ рддрддреНрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
 <CheckBox IsChecked="{Binding EnableDisableCommand.CanExecute, Mode=TwoWay}" Content="Enabled" /> 

рднрд▓реЗ рд╣реА рд╣рдордиреЗ рдХрд╣рд╛рдБ рдФрд░ рдХреИрд╕реЗ рдХрдорд╛рдВрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдореЗрд╢рд╛ рдмреВрд▓рд┐рдпрди рдорд╛рди рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдХрд┐ рдХреИрдиреЗрдХреНрд╕реНрдпреВрдЯ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рджреВрд╕рд░реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ - рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг 5 - рдХрдорд╛рдВрдб рдЯреНрд░рд┐рдЧрд░рд┐рдВрдЧ рдЗрд╡реЗрдВрдЯ
рдЙрджреНрджреЗрд╢реНрдп : рдкрддрд╛ рдХрд░реЗрдВ рдХрд┐ рдХрдорд╛рдВрдб рдХрдм рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдпрд╛ рдЗрд╕реЗ рдХрдм рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдВрдб рдореЗрдВ рджреЛ рдШрдЯрдирд╛рдПрдБ рд╣реЛрддреА рд╣реИрдВ: рдирд┐рд╖реНрдкрд╛рджрд┐рдд - рдХрдорд╛рдВрдб рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рдордп - рдирд┐рд╖реНрдкрд╛рджрдиред рдирд┐рд╖реНрдкрд╛рджрди рдШрдЯрдирд╛ рднреА рдЖрдкрдХреЛ рдПрдХ рдЖрджреЗрд╢ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред

рдорд╣рддреНрд╡рдкреВрд░реНрдг : рдХрдИ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рд╣реИрдВ рдЬрдм рдЙрдкрд░реЛрдХреНрдд рдШрдЯрдирд╛рдПрдВ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛ рдЬрд╛рддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдПрдХ рдкреЙрдк-рдЕрдк рд╡рд┐рдВрдбреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ рдкреВрдЫрддреА рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЖрдк рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдкрд░ рдЬрд╛рд░реА рд░рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдФрд░ рдРрд╕реЗ рдХреЛрдб рдХреЛ рдХрд╣рд╛рдВ рд░рдЦрд╛ рдЬрд╛рдП? рдХрдорд╛рдВрдб рдХреЛрдб рдореЗрдВ? рдпрд╣ рдПрдХ рдмреБрд░рд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдореЗрдВ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛрдб рдмрдирд╛рдирд╛ рд╣реИ, рдЬреЛ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдХреЛрдб рдХреЛ рд░реЛрдХрддреЗ рд╣реИрдВ, рдФрд░ рджреВрд╕рд░реЗ рдореЗрдВ, рдЬреЛ рдХрд┐ рдЕрдзрд┐рдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдпрд╣ рдЗрд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрдЧрд╛ред рдХреЛрдб рдХреЛ рд╡реНрдпреВ рдореЗрдВ рд░рдЦрдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдФрд░ рдШрдЯрдирд╛рдУрдВ рдХреА рдорджрдж рд╕реЗ рдЖрдк рдЗрд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдРрд╕реА рдШрдЯрдирд╛рдУрдВ рдХреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг рд╡рд╣ рд╕реНрдерд┐рддрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИ рдЬрдм рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐рд╕реА рдЕрдиреНрдп рддрддреНрд╡ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдЗрд╕реЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдирд┐рдпрдВрддреНрд░рдг (рдирд┐рдпрдВрддреНрд░рдг) рддрдХ рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдХрд░ рдЖрдк рдЗрд╕реЗ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
 public class MainViewModel : ViewModel { public MainViewModel() { //     eventsCommand = new Command( () => { Messages.Add("   ."); }); 

рдЕрдм рдмрдЯрди рдХреЛ рдмрд╛рдВрдзреЗрдВ:
 <Button Content="Events Command" Command="{Binding EventsCommand}" /> 

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдХреЛрдб рд╕реЗ рдХреЛрдИ рдЕрдВрддрд░ рдирд╣реАрдВ рд╣реИрдВред рджреГрд╢реНрдп рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдВред
рдорд╣рддреНрд╡рдкреВрд░реНрдг: рдореЗрд░реЗ рд╡рд┐рдЪрд╛рд░ рдореЗрдВ, рдПрдХ DataContext рдЬрд┐рд╕рдХрд╛ рдирд╛рдо viewModel рд╣реИ:
 /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); viewModel.EventsCommand.Executing += new Apex.MVVM.CancelCommandEventHandler(EventsCommand_Executing); viewModel.EventsCommand.Executed += new Apex.MVVM.CommandEventHandler(EventsCommand_Executed); } void EventsCommand_Executed(object sender, Apex.MVVM.CommandEventArgs args) { viewModel.Messages.Add("   .  View!"); } void EventsCommand_Executing(object sender, Apex.MVVM.CancelCommandEventArgs args) { if (MessageBox.Show(" ?", "Cancel?", MessageBoxButton.YesNo) == MessageBoxResult.Yes) args.Cancel = true; } } 

рдЕрдВрдд рдореЗрдВ, рд╣рдо рдЯреАрдо рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдкреВрд░реА рд╢рдХреНрддрд┐ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рдХрд░реАрдм рдкрд╣реБрдВрдЪ рдЧрдПред рдХрд┐рд╕реА рджреГрд╢реНрдп рдореЗрдВ (рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп ViewModel, рдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ) рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдФрд░ рд╣рдо рдпрд╣ рднреА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХрдм рд╣реЛрддрд╛ рд╣реИред рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдШрдЯрдирд╛ рд░рджреНрдж рдХрд░рддреА рд╣реИрдорд╣рд┐рд▓рд╛рдУрдВ рдХреЛ рд░рджреНрдж рдХрд░реЗрдВ рд╡рд╕реНрддреБ - рдпрд╣ "рд░рджреНрдж рдХрд░реЗрдВ" рдирд╛рдо рдХреЗ рд╕рд╛рде рд╕рдВрдкрддреНрддрд┐ рд╣реИред рдпрджрд┐ рдЗрд╕реЗ рд╕рд╣реА рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рджреЛрдиреЛрдВ CommandEventArgs рдФрд░ CancelCommandEventArgs рдСрдмреНрдЬреЗрдХреНрдЯ рдПрдХ рдФрд░ рдЧреБрдг - рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╡рд╣ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ рдЬрд┐рд╕реЗ рдХрдорд╛рдВрдб (рдпрджрд┐ рдХреЛрдИ рд╣реЛ) рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЙрджрд╛рд╣рд░рдг 6 - рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдорд╛рдВрдб
рдЙрджреНрджреЗрд╢реНрдп : рдпрджрд┐ рдЖрджреЗрд╢реЛрдВ рдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЕрд╡рд░реБрджреНрдз рд╣реИред рдЙрдиреНрд╣реЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдЪрд▓рд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЖрдк рдПрдХ рдкреГрд╖реНрдарднреВрдорд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рддрд░рд╣ рдХреБрдЫ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╡рд╣рд╛рдВ рдПрдХ рдХрдорд╛рдВрдб рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХрдИ рд╕рд╡рд╛рд▓ рддреБрд░рдВрдд рдЙрдарддреЗ рд╣реИрдВ:
"рдЕрдЧрд░ рд╣рдо рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ ViewModel рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛?" рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓рд┐рдП рдмрд┐рдирд╛ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред
- рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдПрдХ рдЯреАрдо рдиреЗ рдЧрд▓рддреА рд╕реЗ рдХрдИ рдереНрд░реЗрдбреНрд╕ рдХреЛ рдХреЙрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрд░ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рднрд╛рд╡ рд╣реЛрддрд╛ рд╣реИ?
- рд╡реНрдпреВ рдореЙрдбрд▓ рдХреЛ рд▓рд┐рдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдирд╣реАрдВ, рдЕрдЧрд░ рдХрдИ рдХрдорд╛рдВрдб рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛?
- WP рдФрд░ рд╕рд┐рд▓реНрд╡рд░рд▓рд╛рдЗрдЯ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ, рдЕрдЧрд░ рдкреНрд░рддреНрдпреЗрдХ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ?

AsynchronousCommand рдСрдмреНрдЬреЗрдХреНрдЯ рдЗрди рд╕рднреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рди рдХреЗрд╡рд▓ред рдкрд░рд┐рдЪрд┐рдд рд╣реЛ рдЬрд╛рдУ:
 public class MainViewModel : ViewModel { public MainViewModel() { //    asyncCommand1 = new AsynchronousCommand( () => { for (int i = 1; i <= 10; i++) { //    . asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); }); System.Threading.Thread.Sleep(200); } }); } /// <summary> /// The command object. /// </summary> private AsynchronousCommand asyncCommand1; /// <summary> /// Gets the command. /// </summary> public AsynchronousCommand AsyncCommand1 { get { return asyncCommand1; } } } 

XAML рддрддреНрд╡ рд╕реЗ рдмрд╛рдВрдзрдирд╛:
 <Button Content="Asynchronous Command" Command="{Binding AsyncCommand1}" /> 

рдХрдорд╛рдВрдб рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рд▓реИрдореНрдмреНрдбрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдорджрдж рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдереНрд░реЗрдб рдкреВрд▓ рд╕реЗ рдПрдХ рдЕрд▓рдЧ рдереНрд░реЗрдб рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

рдпрджрд┐ рджреГрд╢реНрдп рдореЙрдбрд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрддреНрд╡реЛрдВ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ), рддреЛ рд╣рдо ReportProgress рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); }); 

ReportProgress рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЗрд╖рд┐рдд рдХреЛрдб рд╡рд╛рдВрдЫрд┐рдд рдереНрд░реЗрдб рдореЗрдВ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдиреЗ рдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХрд╛рдлреА рдЖрд╕рд╛рдиреА рд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдЙрджрд╛рд╣рд░рдг 7 - рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ (рдпреВрдЖрдИ) рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрдорд╛рди
рд▓рдХреНрд╖реНрдп : рдЯреАрдо рдХреЛ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдореЗрдВ рд▓рдВрдмрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИред рдкреНрд░рдЧрддрд┐ рдмрд╛рд░ рджрд┐рдЦрд╛рдПрдВред

AsynchronousCommand рдореЗрдВ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рд╣реИ рдЬрд┐рд╕реЗ "IsExecuting" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдпрд╣ рд╕рдЪ рд╣реИ, рддреЛ рдХрдорд╛рдВрдб рдЪрд╛рд▓реВ рд╣реИред рдЪреВрдВрдХрд┐ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕рдХреЙрд╕рдореИрдВрдб INotifyPropertyChanged рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдмрд╛рдВрдзрдиреЗ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджрд┐рдЦрд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред
 public class MainViewModel : ViewModel { public MainViewModel() { //    asyncCommand2 = new AsynchronousCommand( () => { for (char c = 'A'; c <= 'Z'; c++) { //    asyncCommand2.ReportProgress(() => { Messages.Add(c.ToString()); }); System.Threading.Thread.Sleep(100); } }); } /// <summary> /// The command object. /// </summary> private AsynchronousCommand asyncCommand2; /// <summary> /// Gets the command. /// </summary> public AsynchronousCommand AsyncCommand2 { get { return asyncCommand2; } } } 

рд╣рдо рдмрдЯрди рдХреЗ рд╕рд╛рде рдХрдорд╛рдВрдб рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдФрд░ рд╣рдо IsExecuting рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдПрдХ рдЕрдиреНрдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддрддреНрд╡ рд╕реЗ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, StackPanel, рдЬрд┐рд╕рдореЗрдВ рдХреНрд░рдорд╢рдГ TextBlock рдФрд░ ProgressBar рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ:
 <Button Content="Asynchronous Command" Command="{Binding AsyncCommand2}" Visibility="{Binding AsyncCommand2.IsExecuting, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Invert}" /> <StackPanel Visibility="{Binding AsyncCommand2.IsExecuting, Converter={StaticResource BooleanToVisibilityConverter}}"> <TextBlock Text="The command is running!" /> <ProgressBar Height="20" Width="120" IsIndeterminate="True" /> </StackPanel> 

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЬреИрд╕реЗ рд╣реА рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдмрдЯрди рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рд╢рд┐рд▓рд╛рд▓реЗрдЦ рдФрд░ рдкреНрд░рдЧрддрд┐ рдмрд╛рд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдХрдорд╛рдВрдб рдХреЗ IsExecuting рдЧреБрдг рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рд╣реИрдВред
 asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); }); 

рдиреЛрдЯ : рдЗрдирд╡рд░реНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдмреВрд▓рд┐рдпрдирдЯреЙрдЗрдЬрд╝рд┐рд▓рд┐рдЯреАрдХреЙрдиреНрд╡рд░реНрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдорд╛рдирдХ рдмреВрд▓рд┐рдпрдирдЯреЙрдЗрд╕рд┐рдмрд┐рд▓рд┐рдЯреА рдХрд╛ рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рд╣реИ, рдЬреЛ рдПрдкреЗрдХреНрд╕.рдСрдирд╡рд░реНрдЯрд░реНрд╕ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдо рдирд┐рдХрд╛рд▓рддрд╛ рд╣реИред рдХреБрдЫ рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдПрдХ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рдЫреЛрдЯреА рдЪреАрдЬред

рдЙрджрд╛рд╣рд░рдг 8 - рд░рджреНрдж рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрдорд╛рди
рдЙрджреНрджреЗрд╢реНрдп : рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ред

AsynchronousCommand рдХреА рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдПрдВред рдкреНрд░рддреНрдпреЗрдХ AsynchronousCommand рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ CancelCommand рдирд╛рдордХ рдПрдХ рдХрдорд╛рдВрдб рднреА рд╣реЛрддрд╛ рд╣реИред рдФрд░ рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ UI рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рд╕рд╣реА рд╕реНрдерд╛рди рдкрд░ рдХреЛрдб рдХреЗ рдЕрдВрджрд░ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬрдм рдЗрд╕ рдЖрджреЗрд╢ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ AsynchronousCommand рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ IsCancellationRequested рдЧреБрдг рд╕рддреНрдп рдкрд░ рд╕реЗрдЯ рд╣реЛрддрд╛ рд╣реИ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рдВрдкрддреНрддрд┐ INotifyPropertyChanged рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ рдФрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЗрд╕реЗ рдмрд╛рдЗрдВрдб рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рд╣реИ)ред рдЖрдк рд╕рдордп-рд╕рдордп рдкрд░ CancelIfRequested рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдпрд╣ рдЕрдЪрд╛рдирдХ рд╕рдЪ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХрдорд╛рдВрдб рдмрдВрдж рд╣реЛ рдЬрд╛рдПрдЧреАред
 public class MainViewModel : ViewModel { public MainViewModel() { //      cancellableAsyncCommand = new AsynchronousCommand( () => { for(int i = 1; i <= 100; i++) { // ? if(cancellableAsyncCommand.CancelIfRequested()) return; // . cancellableAsyncCommand.ReportProgress( () => { Messages.Add(i.ToString()); } ); System.Threading.Thread.Sleep(100); } }); } /// <summary> /// The command object. /// </summary> private AsynchronousCommand cancellableAsyncCommand; /// <summary> /// Gets the command. /// </summary> public AsynchronousCommand CancellableAsyncCommand { get { return cancellableAsyncCommand; } } } 

рдмрдЯрди рдХреЗ рд▓рд┐рдП рдХрдорд╛рдВрдб рдмрд╛рдБрдзреЗрдВ, рдФрд░ StackPanel рдХреЛ IsExecuting рдЧреБрдг:
 <Button Content="Cancellable Async Command" Command="{Binding CancellableAsyncCommand}" Visibility="{Binding CancellableAsyncCommand.IsExecuting, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Invert}" /> <StackPanel Visibility="{Binding CancellableAsyncCommand.IsExecuting, Converter={StaticResource BooleanToVisibilityConverter}}"> <TextBlock Margin="4" Text="The command is running!" /> <ProgressBar Margin="4" Height="20" Width="120" IsIndeterminate="True" /> <Button Margin="4" Content="Cancel" Command="{Binding CancellableAsyncCommand.CancelCommand}" /> </StackPanel> 

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдХрдорд╛рдВрдб рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд░рджреНрдж рдХрд░реЗрдВ рдмрдЯрди рджрд┐рдЦрд╛рддреЗ рд╣реИрдВред рдпрд╣ рдмрдЯрди рдХреИрдВрд╕рд┐рд▓реЗрдмрд▓рдПрд╕реНрдкрд╛рдВрд╕рдХреЙрдиреНрдб рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред рдХреИрдиреНрд╕реЗрд▓реЗрд▓рдореИрдВрдб рдкреНрд░реЙрдкрд░реНрдЯреАред рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рд╣рдо CancelIfRequested рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдорд╛рдВрдб рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХрдиреЗ рдХрд╛ рдПрдХ рд╕реБрдВрджрд░ рдЕрд╡рд╕рд░ рд╣реИред

рдиреЛрдЯ : рдЬрдм рдЖрдк рдПрдХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдПрдХреНрдЬрд╝рдХреНрдпреВрдЯреЗрдб рдИрд╡реЗрдВрдЯ рдирд╣реАрдВ рдЙрдард╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд░рджреНрдж рдХрд┐рдпрд╛ рдЧрдпрд╛ рдИрд╡реЗрдВрдЯ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдмрдврд╝рд╛ рд╣реИ, рдЬреЛ рд╕рдорд╛рди рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗ рд╕рдХрддрд╛ рд╣реИред

рдЙрджрд╛рд╣рд░рдг 9 - рдХрдорд╛рдВрдб рдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдЗрд╡реЗрдВрдЯ
рдЙрджреНрджреЗрд╢реНрдп : рдПрдХ рдХрдорд╛рдВрдб рдХреЛ рд╕реЗрдЯ рдХрд░реЗрдВ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддрддреНрд╡ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬрд┐рд╕рдореЗрдВ рдХрдорд╛рдВрдб рдкреНрд░реЙрдкрд░реНрдЯреА рд╕реЗрдЯ рдирд╣реАрдВ рд╣реИ рд▓реЗрдХрд┐рди рдПрдХ рдИрд╡реЗрдВрдЯ рд╕реЗрдЯ рд╣реИред

рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдк EventBindings рдЕрдиреБрд▓рдЧреНрди рдЧреБрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ Apex.Commands рд╡рд░реНрдЧ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИред EventBindings рдПрдХ EventBindingCollection рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ EventBinding рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдПрдХ рд╕рд░рд▓ рд╕рдВрдЧреНрд░рд╣ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ EventBinding рджреЛ рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗрддрд╛ рд╣реИ: рдШрдЯрдирд╛ рдХрд╛ рдирд╛рдо рдФрд░ рдХрдорд╛рдВрдб рдХрд╛ рдирд╛рдо рдЬрд┐рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рд╣реИред
 public class MainViewModel : ViewModel { public MainViewModel() { //    EventBindingCommand = new Command( () => { Messages.Add("  ."); }); } /// <summary> /// The command object. /// </summary> private Command eventBindingCommand; /// <summary> /// Gets the command. /// </summary> public Command EventBindingCommand { get { return eventBindingCommand; } } } 

рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдЯреАрдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
 <Border Margin="20" Background="Red"> <!тАФ  EventBindingCommand   MouseLeftButtonDown. --> <apexCommands:EventBindings.EventBindings> <apexCommands:EventBindingCollection> <apexCommands:EventBinding EventName="MouseLeftButtonDown" Command="{Binding EventBindingCommand}" /> </apexCommands:EventBindingCollection> </apexCommands:EventBindings.EventBindings> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="Left Click on Me" FontSize="16" Foreground="White" /> </Border> 

EventBindings рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдХрд┐рд╕реА рднреА рдЖрджреЗрд╢ рдХреЛ рдХрд┐рд╕реА рднреА рдШрдЯрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдХрдорд╛рдВрдб рдХреНрд▓рд╛рд╕
рдХрдорд╛рдВрдб рд╡рд░реНрдЧ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ 1-5 рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
 /// <summary> ///  ViewModelCommand тАУ   ICommand,   . /// </summary> public class Command : ICommand { /// <summary> ///       <see cref="Command"/>. /// </summary> /// <param name="action">.</param> /// <param name="canExecute">  <c>true</c> [can execute] ( ).</param> public Command(Action action, bool canExecute = true) { // Set the action. this.action = action; this.canExecute = canExecute; } /// <summary> ///       <see cref="Command"/> class. /// </summary> /// <param name="parameterizedAction"> .</param> /// <param name="canExecute">    <c>true</c> [can execute]( ).</param> public Command(Action<object> parameterizedAction, bool canExecute = true) { // Set the action. this.parameterizedAction = parameterizedAction; this.canExecute = canExecute; } 

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рджреЛ рдЕрддрд┐рднрд╛рд░рд┐рдд рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдХрд╛рд░реНрд░рд╡рд╛рдИ, рдпрд╛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде: рдХрд╛рд░реНрд░рд╡рд╛рдИ <рдСрдмреНрдЬреЗрдХреНрдЯ>, рдЬрд╣рд╛рдВ рдСрдмреНрдЬреЗрдХреНрдЯ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИред

рдЕрдЧрд▓рд╛, canExecute рдзреНрд╡рдЬ рд╕реЗрдЯ рдХрд░реЗрдВ, рдЬреЛ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред CanExecute рдлреНрд▓реИрдЧ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ canExecuteChanged рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
 /// <summary> /// (  )     . /// </summary> protected Action action = null; protected Action<object> parameterizedAction = null; /// <summary> ///  ,     . /// </summary> private bool canExecute = false; /// <summary> ///  /  ,      /// </summary> /// <value> /// <c>true</c>   ;   - <c>false</c>. /// </value> public bool CanExecute { get { return canExecute; } set { if (canExecute != value) { canExecute = value; EventHandler canExecuteChanged = CanExecuteChanged; if (canExecuteChanged != null) canExecuteChanged(this, EventArgs.Empty); } } } 

рдЕрдЧрд▓рд╛, рд╣рдо ICommand рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ
 /// <summary> ///  , ,        /// </summary> /// <param name="parameter">   . ///      , ///        null.</param> /// <returns> /// >    ;   - false. /// </returns> bool ICommand.CanExecute(object parameter) { return canExecute; } /// <summary> ///  ,      . /// </summary> /// <param name="parameter">    . ///      , ///        null.</param> void ICommand.Execute(object parameter) { this.DoExecute(parameter); } 

рд╣рдо рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж DoExecute рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗред
 /// <summary> /// ,      /// </summary> public event EventHandler CanExecuteChanged; /// <summary> ///      /// </summary> public event CancelCommandEventHandler Executing; /// <summary> /// ,    /// </summary> public event CommandEventHandler Executed; 

рдФрд░ рдЕрдм рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдИрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдЗрдирд╡реЛрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╡реНрдпреБрддреНрдкрдиреНрди рд╡рд░реНрдЧреЛрдВ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗред
 protected void InvokeAction(object param) { Action theAction = action; Action<object> theParameterizedAction = parameterizedAction; if (theAction != null) theAction(); else if (theParameterizedAction != null) theParameterizedAction(param); } protected void InvokeExecuted(CommandEventArgs args) { CommandEventHandler executed = Executed; //    if (executed != null) executed(this, args); } protected void InvokeExecuting(CancelCommandEventArgs args) { CancelCommandEventHandler executing = Executing; // Call the executed event. if (executing != null) executing(this, args); } 

рдиреЛрдЯ : InvokeAction рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдпрд╛ рддреЛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд░рд┐рдпрд╛ рдХрд╣рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЛрдИ рднреА рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
 /// <summary> ///   /// </summary> /// <param name="param">The param.</param> public virtual void DoExecute(object param) { //       CancelCommandEventArgs args = new CancelCommandEventArgs() { Parameter = param, Cancel = false }; InvokeExecuting(args); //     - . if (args.Cancel) return; //    /  ,    .   . InvokeAction(param); // Call the executed function. InvokeExecuted(new CommandEventArgs() { Parameter = param }); } 

DoExecute рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рдпрд╣ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдмрд╕ рдЗрд╕реА рдШрдЯрдирд╛ рдХреЛ рдЙрдард╛рддрд╛ рд╣реИред

рдЙрдкрд░реЛрдХреНрдд рд╡рд░реНрдЧ ICommand рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдФрд░ 1-5 рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдорд╛рдВрдб рдХреНрд▓рд╛рд╕
рдЙрджрд╛рд╣рд░рдг 6-8 рдореЗрдВ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕рдХреЙрд╕рдордВрдб рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдХрдорд╛рдВрдб рд╡рд░реНрдЧ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдмреЙрдХреНрд╕ рдСрдлрд┐рд╕ рдФрд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ:
 /// <summary> ///   -  ,        .. /// </summary> public class AsynchronousCommand : Command, INotifyPropertyChanged { /// <summary> ///       <see cref="AsynchronousCommand"/>. /// </summary> /// <param name="action">.</param> /// <param name="canExecute">    /// <c>true</c>   .</param> public AsynchronousCommand(Action action, bool canExecute = true) : base(action, canExecute) { //   Initialise(); } /// <summary> ///      <see cref="AsynchronousCommand"/>. /// </summary> /// <param name="parameterizedAction"> .</param> /// <param name="canExecute">    <c>true</c> [can execute] ( ).</param> public AsynchronousCommand(Action<object> parameterizedAction, bool canExecute = true) : base(parameterizedAction, canExecute) { //   Initialise(); } 

INotifyPropertyChanged IsExecuting. Initialise, :
 /// <summary> ///   /// </summary> private Command cancelCommand; /// <summary> ///   . /// </summary> public Command CancelCommand { get { return cancelCommand; } } /// <summary> /// / , ,     /// </summary> /// <value> /// <c>true</c>     ;   - <c>false</c>. /// </value> public bool IsCancellationRequested { get { return isCancellationRequested; } set { if (isCancellationRequested != value) { isCancellationRequested = value; NotifyPropertyChanged("IsCancellationRequested"); } } } /// <summary> ///   /// </summary> private void Initialise() { //    cancelCommand = new Command( () => { // Set the Is Cancellation Requested flag. IsCancellationRequested = true; }, true); } 

, , тАФ IsCancellationRequested true. . IsCancellationRequested, , .

, . рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ:
 /// <summary> /// , ,     . /// </summary> private bool isExecuting = false; /// <summary> /// / ,  ,     .. /// </summary> /// <value> /// <c>true</c>    ;  <c>false</c>. /// </value> public bool IsExecuting { get { return isExecuting; } set { if (isExecuting != value) { isExecuting = value; NotifyPropertyChanged("IsExecuting"); } } } 

рдЪрд▓рд┐рдП рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред Cancelled PropertyChanged ( INotifyPropertyChanged):
 /// <summary> /// The property changed event. /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// ,   . /// </summary> public event CommandEventHandler Cancelled;      DoExecute. /// <summary> ///  . /// </summary> /// <param name="param">.</param> public override void DoExecute(object param) { //     ,  . if (IsExecuting) return; //   ,     . CancelCommandEventArgs args = new CancelCommandEventArgs() { Parameter = param, Cancel = false }; InvokeExecuting(args); //   - . if (args.Cancel) return; //   . IsExecuting = true; 

, , .
 //   . #if !SILVERLIGHT callingDispatcher = Dispatcher.CurrentDispatcher; #else callingDispatcher = System.Windows.Application.Current.RootVisual.Dispatcher; #endif 

, , .

, Silverlight WPF.
 // Run the action on a new thread from the thread pool // (this will therefore work in SL and WP7 as well). ThreadPool.QueueUserWorkItem( (state) => { //  . InvokeAction(param); // Fire the executed event and set the executing state. ReportProgress( () => { //     . IsExecuting = false; //  , //    - ,   тАУ  . if(IsCancellationRequested) InvokeCancelled(new CommandEventArgs() { Parameter = param }); else InvokeExecuted(new CommandEventArgs() { Parameter = param }); //    . IsCancellationRequested = false; } ); } ); } 

. , InvokeAction , . , ReportProgress , Executed. ( ), IsExecuting, : Cancelled Executed. , ReportProgress:
 /// <summary> /// Reports progress on the thread which invoked the command. /// </summary> /// <param name="action">The action.</param> public void ReportProgress(Action action) { if (IsExecuting) { if (callingDispatcher.CheckAccess()) action(); else callingDispatcher.BeginInvoke(((Action)(() => { action(); }))); } } 


тАУ Command
EventBindings - WPF Silverlight. WPF EventBindingsCollection FreezableCollection, . Silverlight FreezableCollection, .
 public static class EventBindings { /// <summary> ///  Event Bindings. /// </summary> private static readonly DependencyProperty EventBindingsProperty = DependencyProperty.RegisterAttached("EventBindings", typeof(EventBindingCollection), typeof(EventBindings), new PropertyMetadata(null, new PropertyChangedCallback(OnEventBindingsChanged))); /// <summary> /// Gets the event bindings. /// </summary> /// <param name="o">The o.</param> /// <returns></returns> public static EventBindingCollection GetEventBindings(DependencyObject o) { return (EventBindingCollection)o.GetValue(EventBindingsProperty); } /// <summary> /// Sets the event bindings. /// </summary> /// <param name="o">The o.</param> /// <param name="value">The value.</param> public static void SetEventBindings(DependencyObject o, EventBindingCollection value) { o.SetValue(EventBindingsProperty, value); } /// <summary> /// Called when event bindings changed. /// </summary> /// <param name="o">The o.</param> /// <param name="args">The <see /// cref="System.Windows.DependencyPropertyChangedEventArgs"/> /// instance containing the event data.</param> public static void OnEventBindingsChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) { // Cast the data. EventBindingCollection oldEventBindings = args.OldValue as EventBindingCollection; EventBindingCollection newEventBindings = args.NewValue as EventBindingCollection; // If we have new set of event bindings, bind each one. if (newEventBindings != null) { foreach (EventBinding binding in newEventBindings) { binding.Bind(o); #if SILVERLIGHT // If we're in Silverlight we don't inherit the // data context so we must set this helper variable. binding.ParentElement = o as FrameworkElement; #endif } } } } 

EventBinding.Bind:
 public void Bind(object o) { try { //        EventInfo eventInfo = o.GetType().GetEvent(EventName); // Get the method info for the event proxy. MethodInfo methodInfo = GetType().GetMethod("EventProxy", BindingFlags.NonPublic | BindingFlags.Instance); // Create a delegate for the event to the event proxy. Delegate del = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo); // Add the event handler. (Removing it first if it already exists!) eventInfo.RemoveEventHandler(o, del); eventInfo.AddEventHandler(o, del); } catch (Exception e) { string s = e.ToString(); } } /// <summary> /// Proxy to actually fire the event. /// </summary> /// <param name="o">The object.</param> /// <param name="e">The <see /// cref="System.EventArgs"/> instance /// containing the event data.</param> private void EventProxy(object o, EventArgs e) { #if SILVERLIGHT // If we're in Silverlight, we have NOT inherited the data context // because the EventBindingCollection is not a framework element and // therefore out of the logical tree. However, we can set it here // and update the bindings - and it will all work. DataContext = ParentElement != null ? ParentElement.DataContext : null; var bindingExpression = GetBindingExpression(EventBinding.CommandProperty); if(bindingExpression != null) bindingExpression.UpdateSource(); bindingExpression = GetBindingExpression(EventBinding.CommandParameterProperty); if (bindingExpression != null) bindingExpression.UpdateSource(); #endif if (Command != null) Command.Execute(CommandParameter); } 


Source: https://habr.com/ru/post/In196960/


All Articles