Академический Документы
Профессиональный Документы
Культура Документы
Mvvmwinformsdevexpressway 150420102303 Conversion Gate02 PDF
Mvvmwinformsdevexpressway 150420102303 Conversion Gate02 PDF
DEVEXPRESS WAY
dmitry.garavsky@devexpress.com
MVVM? ?
When capabilities are extended, the
codebase should become smaller.
@Thinking Out Loud
- .
.
MVVM WPF. ...
Notifications
Data binding
View
View
View
Model
Model
Commands
C o n te xt
Data
MVVM
Framework?
,
POCO
DX
(MVVM-driven
design)
MVVM WinForms. ?
Notifications
Data binding
View
View
View
Model
Model
Commands
Events
Methods
Presentation Business Logic
Logic and Data
Code-behind
MVVM MVPVM. Presenter.
class
AccountCollectionViewPresenter
{
public
CollectionViewPresenter(GridView
gridView,
AccountCollectionViewModel
viewModel)
{
gridView.FocusedRowObjectChanged
+=
(s,
e)
=>
{
viewModel.SelectedEntity
=
e.Row
as
Model.Account;
};
((INotifyPropertyChanged)viewModel).PropertyChanged
+=
(s,
e)
=>
{
if(e.PropertyName
==
"SelectedEntity")
{
var
entity
=
viewModel.SelectedEntity;
if(entity
!=
null)
gridView.FocusedRowHandle
=
gridView.LocateByValue("Id",
entity.ID);
else
gridView.FocusedRowHandle
=
GridControl.InvalidRowHandle;
}
};
}
}
MVVM MVPVM. Presenter.
class
AccountCollectionViewPresenter
{
public
CollectionViewPresenter(GridView
gridView,
AccountCollectionViewModel
viewModel)
{
gridView.FocusedRowObjectChanged
+=
(s,
e)
=>
{
viewModel.SelectedEntity
=
e.Row
as
Model.Account;
};
gridView.FocusedRowObjectChanged
+=
(s,
e)
=>
{
((INotifyPropertyChanged)viewModel).PropertyChanged
+=
(s,
e)
=>
{
if(e.PropertyName
==
"SelectedEntity")
{
viewModel.SelectedEntity
=
e.Row
as
Model.Account;
var
entity
=
viewModel.SelectedEntity;
if(entity
!=
null)
};
gridView.FocusedRowHandle
=
gridView.LocateByValue("Id",
entity.ID);
else
gridView.FocusedRowHandle
=
GridControl.InvalidRowHandle;
}
};
}
}
WinForms - Presenter .
User
Control
Code-Behind
Code-Behind
(Binding)
MVPVM P.
,
.
.
.
,
,
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
get
{
return
userNameCore;
}
set
{
if(userNameCore
==
value)
return;
this.userNameCore
=
value;
PropertyChangedEventHandler
handler
=
PropertyChanged;
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
public
class
LoginViewModel
:
BindableBase
{
get
{
return
userNameCore;
}
string
userNameCore;
set
{
if(value
!=
userNameCore)
{
public
string
UserName
{
this.userNameCore
=
value;
get
{
return
userNameCore;
}
PropertyChangedEventHandler
handler
=
PropertyChanged;
set
{
SetProperty(ref
userNameCore,
"UserName");}
if(handler
!=
null)
}
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
POCO-ViewModel:
get
{
return
userNameCore;
}
set
{
if(value
!=
userNameCore)
{
Full-featured
POCO-class
???
ViewModel
DevExpress.Mvvm.POCO.ViewModelSource
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
POCO-ViewModel:
get
{
return
userNameCore;
}
set
{
if(value
!=
userNameCore)
{
this.userNameCore
=
value;
public
class
LoginViewModel
{
PropertyChangedEventHandler
handler
=
PropertyChanged;
public
virtual
string
UserName
{
get;
set;
}
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
}
}
?
XAML:
<UserControl
x:Class="DXPOCO.Views.LoginView"
WinForms Code-behind:
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
public
LoginViewModel
ViewModel
{
xmlns:ViewModels="clr-namespace:DXPOCO.ViewModels"
get
{
return
mvvmContext.GetViewModel<LoginViewModel>();
}
}
DataContext="{dxmvvm:ViewModelSource
Type=ViewModels:LoginViewModel}"
...>
</UserControl>
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
get
{
return
userNameCore;
}
set
{
if(userNameCore
==
value)
return;
this.userNameCore
=
value;
PropertyChangedEventHandler
handler
=
PropertyChanged;
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
OnUserNameChanged();
//
OnUserNameChanged(oldValue)
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
class
LoginViewModel
:
BindableBase
{
public
string
UserName
{
string
userNameCore;
get
{
return
userNameCore;
}
public
string
UserName
{
set
{
get
{
return
userNameCore;
}
if(value
!=
userNameCore)
{
this.userNameCore
=
value;
set
{
PropertyChangedEventHandler
handler
=
PropertyChanged;
SetProperty(ref
userNameCore,
if(handler
!=
null)
"UserName",
OnUserNameChanged);
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
}
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
POCO-ViewModel:
get
{
return
userNameCore;
}
set
{
if(value
!=
userNameCore)
{
this.userNameCore
=
value;
public
class
LoginViewModel
{
PropertyChangedEventHandler
handler
=
PropertyChanged;
public
virtual
string
UserName
{
get;
set;
}
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
protected
void
OnUserNameChanged()
{/*...*/}
}
}
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
public
string
UserName
{
get
{
return
userNameCore;
}
set
{
if(userNameCore
==
value)
return;
this.userNameCore
=
value;
PropertyChangedEventHandler
handler
=
PropertyChanged;
PropertyChangedEventHandler
handler
=
PropertyChanged;
if(handler
!=
null)
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
OnUserNameChanged();
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
public
class
LoginViewModel
:
INotifyPropertyChanged
{
public
event
PropertyChangedEventHandler
PropertyChanged;
string
userNameCore;
POCO-ViewModel:
public
string
UserName
{
get
{
return
userNameCore;
}
set
{
if(value
!=
userNameCore)
{
//
Extension
method
this.userNameCore
=
value;
this.RaisePropertyChanged(x
=>
x.UserName);
PropertyChangedEventHandler
handler
=
PropertyChanged;
if(handler
!=
null)
handler(this,
new
PropertyChangedEventArgs("UserName"));
}
}
}
}
?
public
class
DelegateCommand<T>
:
System.Windows.Input.ICommand
{
readonly
Predicate<T>
_canExecute;
public
class
MyViewModel
{
readonly
Action<T>
_execute;
public
MyViewModel()
{
public
DelegateCommand(Action<T>
execute)
this.SayHelloCommand
=
new
DelegateCommand(SayHello);
:
this(execute,
null)
{
}
}
public
DelegateCommand(Action<T>
execute,
Predicate<T>
canExecute)
{
public
System.Windows.Input.ICommand
SayHelloCommand
{
_execute
=
execute;
get;
_canExecute
=
canExecute;
private
set;
}
}
//...
public
void
SayHello()
{
/*
do
something
*/
}
}
}
POCO-ViewModel:
public
class
DelegateCommand<T>
:
System.Windows.Input.ICommand
{
readonly
Predicate<T>
_canExecute;
public
class
MyViewModel
{
POCO-ViewModel:
readonly
Action<T>
_execute;
public
void
SaySomething(string
str)
{
public
DelegateCommand(Action<T>
execute)
public
class
MyViewModel
{
:
this(execute,
null)
{
/*
...
*/
}
public
Task
DoSomething
()
{
public
void
SayHello()
{
/*
do
something
*/
}
public
DelegateCommand(Action<T>
execute,
Predicate<T>
canExecute)
{
}
}
_execute
=
execute;
/*
asynchronous
!!!
*/
public
bool
CanSaySomething(string
str)
{
_canExecute
=
canExecute;
}
}
/*
...
*/
}
//...
}
}
}
?
XAML:
<Button
Command="{Binding
SayHello}"
/>
<Button
Command="{Binding
Say}"
CommandParameter="Hello!"/>
?
WinForms Code-behind (MVVMContext API):
public
MyViewModel
ViewModel
{
get
{
return
mvvmContext.GetViewModel<MyViewModel>();
}
WinForms Code-behind (MVVMContext Fluent API):
}
var
fluentApi
=
mvvmContext.OfType<MyViewModel>();
//
fluentApi.BindCommand(x
=>
x.SayHello());
btnSayHello.BindCommand(
fluentApi.BindCommand((x,s)
=>
x.Say(s),
x
=>
x.Name);
()
=>
ViewModel.SayHello(),
ViewModel);
btnSay.BindCommand(
()
=>
ViewModel.Say(null),
ViewModel,
()
=>
ViewModel.Name);
. .
ViewModel:
public
class
MyViewModel
{
protected
IMessageBoxService
MessageBoxService
{
get
{
/*
...
*/
}
}
public
void
SayHello()
{
MessageBoxService.Show("Hello!");
}
}
. .
POCO ViewModel:
protected
IMessageBoxService
MessageBoxService
{
get
{
this.GetService<IMessageBoxService>();
}
}
protected
virtual
IMessageBoxService
MessageBoxService
{
get
{
throw
new
System.NotImplementedException();
}
}
?
.
WinForms Code-behind (MVVMContext Fluent API):
//...
mvvmContext.WithEvent<CancelEventArgs>(this,
"Closing")
.Confirmation(
settings
=>
{
settings.Caption
=
"Closing
Confirmation";
settings.Text
=
"Form
will
be
closed.
Press
OK
to
confirm.";
settings.Buttons
=
ConfirmationButtons.OKCancel;
settings.ShowQuestionIcon
=
false;
});
. EventToCommand.
public
class
ClickToSayHello
:
EventToCommandBehavior<MyViewModel,
EventArgs>
{
public
ClickToSayHello()
:
base("Click",
x
=>
x.SayHello())
{
}
}
Entity Framework 6.x (Nuget)
DevExpress MVVM Framework
CRUD- Expenses.
DevExpress Scaffolding Wizard
DevExpress WinForms Controls
. Model.
(XtraGrid)
var
fluent
=
mvvmContext.OfType<AccountCollectionViewModel>();
fluent.SetBinding(gridView,
v
=>
v.LoadingPanelVisible,
x
=>
x.IsLoading);
fluent.SetBinding(gridControl,
g
=>
g.DataSource,
x
=>
x.Entities);
fluent.WithEvent<ColumnView,
FocusedRowObjectChangedEventArgs>(
gridView,
"FocusedRowObjectChanged")
.SetBinding(x
=>
x.SelectedEntity,
args
=>
args.Row
as
Model.Account,
(gView,
entity)
=>
gView.FocusedRowHandle
=
gView.FindRow(entity));
fluent.WithEvent<RowCellClickEventArgs>(gridView,
"RowCellClick")
.EventToCommand(
x
=>
x.Edit(null),
x
=>
x.SelectedEntity,
args
=>
(args.Clicks
==
2)
&&
(args.Button
==
MouseButtons.Left));
(DataLayout)
[DataType(DataType.Date)]
[Display(Name
=
"DATE")]
public
DateTime
Date
{
get;
set;
}
[Required,
StringLength(30,
MinimumLength
=
4)]
[DataType(DataType.Currency)]
[Display(Name
=
"ACCOUNT")]
[Display(Name
=
"AMOUNT")]
public
string
Name
{
get;
set;
}
public
decimal
Amount
{
get;
set;
}
[DataType(DataType.MultilineText)]
[Display(Name
=
"COMMENT")]
public
string
Comment
{
get;
set;
}
DocumentManagerService -
( QueryControl):
MessageBoxService -
(, , Flyout):
tabbedView.QueryControl
+=
(s,
e)
=>
{
if(e.Document.ControlName
==
"AccountCollectionView")
DevExpress.Utils.MVVM.MVVMContext.RegisterFlyoutMessageBoxService();
e.Control
=
new
Views.Accounts();
};
MVVM
+
DevExpress
(WPF/Silverlight/WinForms/WinRT/UAP)
!
dmitry.garavsky@devexpress.com
WWW.DEVEXPRESS.COM
support@devexpress.com
:
1. DevExpress
MVVM
Framework
and
MVVM(MVPVM)
Architectural
Pa{ern
in
WinForms
2. MVVM
In
Ac~on:
Expenses
App
-
Displaying
and
naviga~ng
between
DB
Collec~ons(Tutorial
01)
3. MVVM
In
Ac~on:
Expenses
App
Displaying
DB
En~ty
details.
DB
En~ty
proper~es
edi~ng.(Tutorial
02)
:
1.
Expenses
(
DevExpress
Code
Central)
2. DevExpress.MVVM.Free
(github)