The most common pattern in WPF
is MVVM
(Model-View-ViewModel) which is a default of type MV*
.
In this pattern there are 3 components. The view (which has a set of controls arranged in a certain way), the model (which has the data with logic) and the ViewModel (which has the information to be presented in the view, as well as the events of the controls, such as buttons).
InMVVMitistypicalforcontrolstosupportdata-binding
.Thisisjusttosaythataparticularcontrolpropertyisboundtoaclassproperty.ForexamplethetextinatextboxmaybelinkedtoaNome
property.Bindingsalsorefreshtheviewautomaticallyaslongastheynotifytheview.Tonotifytheviewitisnecessary,inWPF
,toimplementtheinterfaceINotififyPropertyChanged
andtoinvoketheeventPropertyChanged
publicclassModel:INotifyPropertyChanged{publiceventPropertyChangedEventHandlerPropertyChanged;[NotifyPropertyChangedInvocator]protectedvirtualvoidOnPropertyChanged([CallerMemberName]stringpropertyName=null){PropertyChanged?.Invoke(this,newPropertyChangedEventArgs(propertyName));}protectedboolSetField<T>(refTfield,Tvalue,[CallerMemberName]stringpropertyName=null){if(!field.Equals(value)){field=value;OnPropertyChanged(propertyName);returntrue;}returnfalse;}}
TheSetFieldmethodisasimplewaytoinvoketheevent.Itonlyinvokesifthevaluechanges.YourViewsModelscannowderivefromthisclass.
publicclassPessoaViewModel:Model{privatestring_nome;publicstringNome{get{return_nome;}set{SetField(ref_nome,value);}}}
AsIexplainedbefore,thecommandscanalsobebinded
.CommandsshouldimplementtheICommand
interface.Inordertoavoidcreatingaclassforeachtypeofcommand,itiscommontocreateonethatexecutesanyAction
,passedintheclassconstructor:
publicclassDelegatedCommand:ICommand{protectedreadonlyAction<object>_action;protectedPredicate<object>_canExecute;publicDelegatedCommand(Action<object>action,Predicate<object>canExecute=null){_action=action;_canExecute=canExecute;}publicboolCanExecute(objectparameter){return_canExecute?.Invoke(parameter)??true;}publicvoidExecute(objectparameter){_action(parameter);}publiceventEventHandlerCanExecuteChanged{add{CommandManager.RequerySuggested+=value;}remove{CommandManager.RequerySuggested-=value;}}}
YoucannowaddcommandstoyourViewModel.Thereareseveralwaystodothis,butI'llshowyoutheoneIusuallyuse:
publicclassPessoaViewModel:Model{privateICommand_command;publicICommandCommand{get{if(_command!=null)return_command;return_command=newDelegtedCommand((arg)=>{Console.WriteLine("O código do comando vai aqui");
});
}
}
}
Of course the commands can change the state of the properties, if they invoke PropertyChanged
then the interface will be updated automatically.
Finally a fairly simple view (omitted some attributes of Window):
<Window>
<Window.DataContext>
<local:PessoaViewModel />
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Nome}" />
<Button Command="{Binding Command}" />
</Stackpanel>
</Window>
References
What is MVP and MVVM