सामग्री की तालिका
- परिचय
- प्रारम्भिक प्रिज्म अनुप्रयोग
- घटकों के बीच निर्भरता का प्रबंधन
- मॉड्यूलर अनुप्रयोग विकास
- एमवीवीएम पैटर्न को लागू करना
- उन्नत MVVM परिदृश्य
- उपयोगकर्ता इंटरफ़ेस निर्माण
- उपयोगकर्ता इंटरफ़ेस दिशानिर्देश
- नेविगेशन
- दृश्य-आधारित नेविगेशन
- शिथिल युग्मित घटकों के बीच पारस्परिक क्रिया
पिछले अध्याय में बताया गया है कि यूजर इंटरफेस, प्रेजेंटेशन लॉजिक और बिजनेस लॉजिक को अलग-अलग वर्गों (प्रेजेंटेशन, प्रेजेंटेशन मॉडल और मॉडल) में अलग करके MVVM पैटर्न के मुख्य तत्वों को कैसे बनाया जाए, उनके बीच इंटरेक्शन लागू करें (डेटा, कमांड्स और डेटा वैलिडिटी इंटरफेस को बाइंड करके)। , उनके निर्माण और अनुकूलन को व्यवस्थित करें।
इन मूल तत्वों का उपयोग करके MVVM पैटर्न को लागू करने से आपके एप्लिकेशन में अधिकांश परिदृश्य फिट होने की संभावना है। हालाँकि, आप अधिक जटिल परिदृश्यों का सामना कर सकते हैं जिनके लिए MVVM पैटर्न के विस्तार, या अधिक उन्नत विधियों के उपयोग की आवश्यकता होती है। ऐसा होने की सबसे अधिक संभावना है यदि आपका आवेदन बड़ा या जटिल है, लेकिन यह कई छोटे अनुप्रयोगों में पाया जा सकता है। प्रिज्म लाइब्रेरी ऐसे घटक प्रदान करती है जो इनमें से कई तरीकों को लागू करते हैं, जिससे आप आसानी से अपने अनुप्रयोगों में इनका उपयोग कर सकते हैं।
यह अध्याय कुछ जटिल परिदृश्यों का वर्णन करता है और एमवीवीएम पैटर्न उनका समर्थन कैसे करता है। अगला खंड दिखाता है कि टीमों को कैसे जंजीर से जोड़ा जा सकता है या बच्चे के विचारों से जोड़ा जा सकता है, और उन्हें कस्टम आवश्यकताओं का समर्थन करने के लिए कैसे बढ़ाया जा सकता है। निम्न अनुभागों का वर्णन है कि उपयोगकर्ता इंटरफ़ेस के साथ अतुल्यकालिक डेटा अनुरोधों और बाद की बातचीत को कैसे संभालना है, साथ ही एक दृश्य और एक दृश्य मॉडल के बीच बातचीत के अनुरोधों को कैसे संभालना है।
एडवांस्ड क्रिएशन एंड कस्टमाईज़ेशन सेक्शन, इनविटेशन इंजेक्शन कंटेनर, जैसे कि एकता एप्लीकेशन ब्लॉक (यूनिटी), या मैनेज एक्स्टेंसिबिलिटी फ्रेमवर्क (MEF) का उपयोग करते समय घटकों को बनाने और कस्टमाइज़ करने का एक सिंहावलोकन प्रदान करता है। अंतिम खंड एमवीवीएम अनुप्रयोगों का परीक्षण करने का तरीका बताता है, और इकाई परीक्षण मॉडल कक्षाओं और प्रस्तुति मॉडल के साथ-साथ व्यवहार परीक्षण का परिचय देता है।
आदेशों
UI. , . , «» 5, , , , : ,
Command
, .
. WPF.
H , , , MVVM WPF , ( Silverlight ). WPF UI. , UI , . , UI, , . WPF , code-behind , .
, , , , . , , .
, , , , . ,
Save All Save
, , .

Prism
CompositeCommand
.
CompositeCommand
, . , . , UI, -, , .
,
CompositeCommand
Stock Trader RI,
SubmitAllOrders
,
Submit All buy/sell .
Submit All,
SubmitCommand
, buy/sell .
CompositeCommand
(
DelegateCommand
).
Execute
CompositeCommand
Execute
.
CanExecute
CanExecute
, - ,
CanExecute
false
. , ,
CompositeCommand
, .
RegisterCommand
UnregisterCommand
.
Stock Trader RI, ,
Submit
Cancel
buy/sell
SubmitAllOrders
CancelAllOrders
, (.
OrdersController
).
commandProxy.SubmitAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.SubmitCommand);
commandProxy.CancelAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.CancelCommand);
commandProxy
Submit
Cancel
, . , StockTraderRICommands.cs
.
, UI, , , , . , , , . ,
DelegateCommand
CompositeCommand
Prism.
Prism ( , «» 7) UI. , UI. , . ,
EditRegion
, UI
TabControl
, .

, , . , , ,
Save All, . , . , , . ,
Zoom , , .

, Prism
IActiveAware
.
IActiveAware
IsActive
,
true
, ,
IsActiveChanged
, , .
IActiveAware
. , , , . , , . ,
TabControl
, , , .
DelegateCommand
IActiveAware
.
true
monitorCommandActivity
,
CompositeCommand
,
DelegateCommand
(
CanExecute
).
true
,
CompositeCommand
DelegateCommand
,
CanExecute
Execute
.
monitorCommandActivity
true
,
CompositeCommand
:
CanExecute
. true
, . , , .Execute
. . , , .
, , .
IActiveAware
, , . , . ,
Zoom
, .
, , — UI , ( ).
, , ,
ListBox
. , , ,
Delete
, .

Delete
, ,
Delete
UI ,
Delete
, . - ,
ListBox
,
Delete
.
– ,
ElementName
, , . XAML .
<Grid x:Name="root">
<ListBox ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Path=Name}"
Command="{Binding ElementName=root,
Path=DataContext.DeleteCommand}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Name
.
Delete
. .
CommandParameter
, , , , (
CollectionView
).
Silverlight 3 , Silverlight , .
ICommand
,
Command
,
ICommand
. MVVM Silverlight 3, Prism ( 2.0) , Silverlight , . WPF, Silverlight, WPF.
, Prism , , .
<Button Content="Submit All"
prism:Click.Command="{Binding Path=SubmitAllCommand}"
prism:Click.CommandParameter="{Binding Path=TickerSymbol}" />
Silverlight 4
Command
Hyperlink
ButtonBase
, WPF.
Command
"
Commands" 5, "
Implementing the MVVM Pattern". , Prism , .
. , , , . Microsoft Expression Blend ,
InvokeCommandAction
CallMethodAction
, , «Invoking Command Methods from the View» 5, "
Implementing the MVVM Pattern", Expression Blend Behaviors SDK . Expression Blend , . Expression Blend, . "
Creating Custom Behaviors" MSDN.
Silverlight 4 Expression Blend Behaviors SDK Prism, , .
. , , , . : . . , .
,
Click
ButtonBase
- ,
ButtonBaseClickCommandBehavior
.
ButtonBase
,
ButtonBaseClickCommandBehavior
,
ICommand
, .

, ,
Click
ButtonBase
, , , , , . / .
Prism
CommandBehaviorBase , , ICommand
. CanExecuteChanged
, Silverlight, WPF.
, , CommandBehaviorBase , . , . , . ButtonBaseClickCommandBehavior
.
public class ButtonBaseClickCommandBehavior : CommandBehaviorBase<ButtonBase> {
public ButtonBaseClickCommandBehavior(ButtonBase clickableObject) : base(clickableObject) {
clickableObject.Click += OnClick;
}
private void OnClick(object sender, System.Windows.RoutedEventArgs e) {
ExecuteCommand();
}
}
CommandBehaviorBase , . , , . , , , , , CanExecute
, .
, . XAML. . . Prism , , , . , . , , , Click
, Command
. Click.Command
, .
. .
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(Click),
new PropertyMetadata(OnSetCommandCallback));
private static readonly DependencyProperty ClickCommandBehaviorProperty =
DependencyProperty.RegisterAttached(
"ClickCommandBehavior",
typeof(ButtonBaseClickCommandBehavior),
typeof(Click),
null);
Command
ButtonBaseClickCommandBehavior
, OnSetCommandCallback
, .
private static void OnSetCommandCallback(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e) {
ButtonBase buttonBase = dependencyObject as ButtonBase;
if (buttonBase != null) {
ButtonBaseClickCommandBehavior behavior = GetOrCreateBehavior(buttonBase);
behavior.Command = e.NewValue as ICommand;
}
}
private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
ButtonBase buttonBase = dependencyObject as ButtonBase;
if (buttonBase != null) {
ButtonBaseClickCommandBehavior behavior = GetOrCreateBehavior(buttonBase);
behavior.CommandParameter = e.NewValue;
}
}
private static ButtonBaseClickCommandBehavior GetOrCreateBehavior(ButtonBase buttonBase ) {
ButtonBaseClickCommandBehavior behavior =
buttonBase.GetValue(ClickCommandBehaviorProperty) as ButtonBaseClickCommandBehavior;
if ( behavior == null ) {
behavior = new ButtonBaseClickCommandBehavior(buttonBase);
buttonBase.SetValue(ClickCommandBehaviorProperty, behavior);
}
return behavior;
}
, Attached Properties Overview MSDN.
. , Silverlight, -, , , . , .
, ( ) , , . UI , UI.
-
- , IAsyncResult
. , , , GetQuestionnaire
, : BeginGetQuestionnaire
EndGetQuestionnaire
. , BeginGetQuestionnaire
. , , EndGetQuestionnaire
.
.NET Framework 4.5 await
async
*Async
. "Asynchronous Programming with Async and Await (C# and Visual Basic)".
, EndGetQuestionnaire
, , () BeginGetQuestionnaire
. , , EndGetQuestionnaire
, .
IAsyncResult asyncResult = this.service.BeginGetQuestionnaire(
GetQuestionnaireCompleted,
null // ,
);
private void GetQuestionnaireCompleted(IAsyncResult result) {
try {
questionnaire = this.service.EndGetQuestionnaire(ar);
}
catch (Exception ex) {
// - .
}
}
, End*
( , EndGetQuestionnaire
), , . , , UI. , , .
UI, -, UI, UI, Dispatcher
SynchronizationContext
. WPF Silverlight, Dispatcher
.
Questionnaire
, QuestionnaireView
. Silverlight CheckAccess
, , UI. , BeginInvoke
, UI.
var dispatcher = System.Windows.Deployment.Current.Dispatcher;
if (dispatcher.CheckAccess()) {
QuestionnaireView.DataContext = questionnaire;
}
else {
dispatcher.BeginInvoke(() => { Questionnaire.DataContext = questionnaire; });
}
MVVM RI , , IAsyncResult
, . , . , .
this.questionnaireRepository.GetQuestionnaireAsync(
result => {
this.Questionnaire = result.Result;
});
result
, , , , . , .
this.questionnaireRepository.GetQuestionnaireAsync(
result => {
if (result.Error == null) {
this.Questionnaire = result.Result;
...
}
else {
}
})
, . , , . , , , .
, MVVM, , . , -MVVM , MessageBox
code-behind UI, . MVVM , .
MVVM, , . , , , , .
MVVM. , , , , . , , , . .
. , . , . .
, , , . , . , . , WPF Silverlight, .

, MessageBox
, , , .
var result =
interactionService.ShowMessageBox(
"Are you sure you want to cancel this operation?",
"Confirm",
MessageBoxButton.OK);
if (result == MessageBoxResult.Yes) {
CancelRequest();
}
, - , , Silverlight. . . .
interactionService.ShowMessageBox(
"Are you sure you want to cancel this operation?",
"Confirm",
MessageBoxButton.OK,
result => {
if (result == MessageBoxResult.Yes) {
CancelRequest();
}
});
, . , WPF MessageBox
, ; Silverlight , .
– . , . , . , , , .

, , – , , – . , , , UI .
MVVM, , , . , , , .
Prism IInteractionRequest
InteractionRequest . IInteractionRequest
, . , . InteractionRequest IInteractionRequest
Raise
, , , , .
InteractionRequest . Raise
( T
) , , . , . , . , , .
public interface IInteractionRequest {
event EventHandler<InteractionRequestedEventArgs> Raised;
}
public class InteractionRequest<T> : IInteractionRequest {
public event EventHandler<InteractionRequestedEventArgs> Raised;
public void Raise(T context, Action<T> callback) {
var handler = this.Raised;
if (handler != null) {
handler(
this,
new InteractionRequestedEventArgs(context, () => callback(context)));
}
}
}
Prism , . Notification
. , . – Title
Content
, . , , , , .
Confirmation
Notification
– Confirmed
, , , . Confirmation
, MessageBox
, / . , Notification
, , .
InteractionRequest , InteractionRequest , . , Raise
, , , .
public IInteractionRequest ConfirmCancelInteractionRequest {
get {
return this.confirmCancelInteractionRequest;
}
}
this.confirmCancelInteractionRequest.Raise(
new Confirmation("Are you sure you wish to cancel?"),
confirmation => {
if (confirmation.Confirmed) {
this.NavigateToQuestionnaireList();
}
});
}
MVVM Reference Implementation (MVVM RI) , IInteractionRequest
InteractionRequest , (. QuestionnaireViewModel.cs
).
, . , . UI .
. Microsoft Expression Blend Behaviors Framework . , , .
EventTrigger
, Expression Blend, , , , . , Prism EventTrigger
, InteractionRequestTrigger
, Raised
IInteractionRequest
. XAML .
, , InteractionRequestTrigger
. Silverlight Prism PopupChildWindowAction
, . , . ContentTemplate
PopupChildWindowAction
, , UI, Content
. Title
.
, , PopupChildWindowAction
, . Notification
NotificationChildWindow
, Confirmation
– ConfirmationChildWindow
. NotificationChildWindow
, , ConfirmationChildWindow
OK Cancel, . , , ChildWindow
PopupChildWindowAction
.
, InteractionRequestTrigger
PopupChildWindowAction
, RI MVVM.
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger
SourceObject="{Binding ConfirmCancelInteractionRequest}">
<prism:PopupChildWindowAction
ContentTemplate="{StaticResource ConfirmWindowTemplate}"/>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<UserControl.Resources>
<DataTemplate x:Key="ConfirmWindowTemplate">
<Grid MinWidth="250" MinHeight="100">
<TextBlock TextWrapping="Wrap" Grid.Row="0" Text="{Binding}"/>
</Grid>
</DataTemplate>
</UserControl.Resources>
ContentTemplate
, UI Content
. Content
, , TextBlock
Content
.
, , , . , , , , . , RI MVVM, Confirmed
Confirmation
true
, OK.
, . Prism InteractionRequestTrigger
PopupChildWindowAction
.
MVVM, , , , . ( , , , ). , , , .
, . Managed Extensibility Framework (MEF) Unity Application Block (Unity) , , .
, , , , ( ) . , , . , , .
, MEF
MEF, , Import
, , , Export
. , .
, QuestionnaireView
RI MVVM, , Import
. , MEF . set
, .
[Import]
public QuestionnaireViewModel ViewModel {
set { this.DataContext = value; }
}
, .
[Export]
public class QuestionnaireViewModel : NotificationObject {
...
}
, .
public QuestionnaireView() {
InitializeComponent();
}
[ImportingConstructor]
public QuestionnaireView(QuestionnaireViewModel viewModel) : this() {
this.DataContext = viewModel;
}
MEF, Unity. , , . , Visual Studio Expression Blend, , , . , , , , InitializeComponent
.
, Unity
Unity, , MEF. , . , . , .
, , , . , , .
public QuestionnaireView() {
InitializeComponent();
}
public QuestionnaireView(QuestionnaireViewModel viewModel) : this() {
this.DataContext = viewModel;
}
, , Visual Studio Expression Blend.
, , . Unity set
, .
public QuestionnaireView() {
InitializeComponent();
}
[Dependency]
public QuestionnaireViewModel ViewModel {
set { this.DataContext = value; }
}
Unity.
container.RegisterType<QuestionnaireViewModel>();
, .
var view = container.Resolve<QuestionnaireView>();
,
, , . , MEF Unity, .
. , UI, .
, RI MVVM , , . , . ShowView
UI.
private void NavigateToQuestionnaireList() {
this.uiService.ShowView(ViewNames.QuestionnaireTemplatesList);
}
UI UI . UI. ShowView
UIService
(, ), , .
public void ShowView(string viewName) {
var view = this.ViewFactory.GetView(viewName);
this.MainWindow.CurrentView = view;
}
Prism . , , , . , , "View-Based Navigation" 8, "Navigation".
MVVM
MVVM . - mocking . , , .
INotifyPropertyChanged
INotifyPropertyChanged
, . , ; , , , , .
, , PropertyChanged
, . , ChangeTracker
, MVVM, , . . , .
var changeTracker = new PropertyChangeTracker(viewModel);
viewModel.CurrentState = "newState";
CollectionAssert.Contains(changeTracker.ChangedProperties, "CurrentState");
, , INotifyPropertyChanged
, , , .
, , set
, . , , , , .
var changeTracker = new PropertyChangeTracker(viewModel);
var question = viewModel.Questions.First() as OpenQuestionViewModel;
question.Question.Response = "some text";
CollectionAssert.Contains(changeTracker.ChangedProperties, "UnansweredQuestions");
INotifyPropertyChanged
, PropertyChanged
, , , , . , .
INotifyDataErrorInfo
, , , , IDataErrorInfo
, ( Silverlight) INotifyDataErrorInfo
. INotifyDataErrorInfo
, , , , , .
INotifyDataErrorInfo
: , , , , ErrorsChanged
, GetErrors
, .
, , . , GetErrors
, , , . , , , , . , .
var notifyErrorInfo = (INotifyDataErrorInfo)question;
question.Response = -15;
Assert.IsTrue(notifyErrorInfo.GetErrors("Response").Cast<ValidationResult>().Any());
var notifyErrorInfo = (INotifyDataErrorInfo)question;
question.Response = 15;
Assert.IsFalse(notifyErrorInfo.GetErrors("Response").Cast<ValidationResult>().Any());
, , .
INotifyDataErrorInfo
GetErrors
, INotifyDataErrorInfo
, ErrorsChanged
GetErrors
. , HasErrors
, .
INotifyDataErrorInfo
. , , , - . , INotifyDataErrorInfo
(, ).
, , :
HasErrors
. , .ErrorsChanged
, , GetErrors
. ( , ) , . GetErrors
ErrorsChanged
.
INotifyPropertyChanged
, , NotifyDataErrorInfoTestHelper
MVVM, INotifyDataErrorInfo
, . , , , . .
var helper =
new NotifyDataErrorInfoTestHelper<NumericQuestion, int?>(
question,
q => q.Response);
helper.ValidatePropertyChange(
6,
NotifyDataErrorInfoBehavior.Nothing);
helper.ValidatePropertyChange(
20,
NotifyDataErrorInfoBehavior.FiresErrorsChanged
| NotifyDataErrorInfoBehavior.HasErrors
| NotifyDataErrorInfoBehavior.HasErrorsForProperty);
helper.ValidatePropertyChange(
null,
NotifyDataErrorInfoBehavior.FiresErrorsChanged
| NotifyDataErrorInfoBehavior.HasErrors
| NotifyDataErrorInfoBehavior.HasErrorsForProperty);
helper.ValidatePropertyChange(
2,
NotifyDataErrorInfoBehavior.FiresErrorsChanged);
MVVM, , . , , .
, , , . , , , , , IAsyncResult
, - , , UI.
, , , . , . , UI, , , , , " UI."
, , . , , mock-, , , , , .
UI, , . , , , . , . , , .
questionnaireRepositoryMock
.Setup(
r =>
r.SubmitQuestionnaireAsync(
It.IsAny<Questionnaire>(),
It.IsAny<Action<IOperationResult>>()))
.Callback<Questionnaire, Action<IOperationResult>>(
(q, a) => callback = a);
uiServicemock
.Setup(svc => svc.ShowView(ViewNames.QuestionnaireTemplatesList))
.Callback<string>(viewName => requestedViewName = viewName);
submitResultMock
.Setup(sr => sr.Error)
.Returns<Exception>(null);
CompleteQuestionnaire(viewModel);
viewModel.Submit();
callback(submitResultMock.Object);
Assert.AreEqual(ViewNames.QuestionnaireTemplatesList, requestedViewName);
, .
, . "Trees in WPF" MSDN: http://msdn.microsoft.com/en-us/library/ms753391.aspx
, . "Attached Properties Overview" MSDN: http://msdn.microsoft.com/en-us/library/cc265152(VS.95).aspx
MEF, ."Managed Extensibility Framework Overview" MSDN: http://msdn.microsoft.com/en-us/library/dd460648.aspx.
Unity, ."Unity Application Block" MSDN: http://www.msdn.com/unity.
DelegateCommand
, .Chapter 5, "Implementing the MVVM Pattern."
Microsoft Expression Blend, ."Working with built-in behaviors" MSDN: http://msdn.microsoft.com/en-us/library/ff724013(v=Expression.40).aspx.
Microsoft Expression Blend, ."Creating Custom Behaviors" MSDN: http://msdn.microsoft.com/en-us/library/ff724708(v=Expression.40).aspx.
Microsoft Expression Blend, ."Creating Custom Triggers and Actions" MSDN: http://msdn.microsoft.com/en-us/library/ff724707(v=Expression.40).aspx.
WPF Silverlight, ."Threading Model" "The Dispatcher Class" MSDN: http://msdn.microsoft.com/en-us/library/ms741870.aspx
http://msdn.microsoft.com/en-us/library/ms615907(v=VS.95).aspx.
unit- Silverlight, ."Unit Testing with Silverlight 2": http://www.jeff.wilcox.name/2008/03/silverlight2-unit-testing/.
, . "View-Based Navigation" in Chapter 8, "Navigation."
, , ."Event-based Asynchronous Pattern Overview" MSDN: http://msdn.microsoft.com/en-us/library/wewwczdw.aspx
IAsyncResult
, ."Asynchronous Programming Overview" MSDN: http://msdn.microsoft.com/en-us/library/ms228963.aspx