एमवीवीएम - दृश्यमोडल को हुक करना
इस अध्याय में, हम ViewModel को हुक करने के तरीके को कवर करेंगे। यह अंतिम अध्याय की एक निरंतरता है जिसमें हमने व्यू फर्स्ट कंस्ट्रक्शन पर चर्चा की। अब, पहले निर्माण का अगला रूप ए हैmeta-pattern जिसे के रूप में जाना जाता है ViewModelLocator। यह एक छद्म पैटर्न है और MVVM पैटर्न के शीर्ष पर स्तरित है।
MVVM में प्रत्येक दृश्य को इसके ViewModel तक पहुंचाने की आवश्यकता होती है।
ViewModelLocator कोड को केंद्रीकृत करने और दृश्य को अधिक डिकूप करने के लिए एक सरल तरीका है।
इसका मतलब है कि यह ViewModel प्रकार और इसके निर्माण के बारे में स्पष्ट रूप से नहीं जानता है।
ViewModelLocator का उपयोग करने के लिए कई अलग-अलग दृष्टिकोण हैं, लेकिन यहां हम PRISM ढांचे के हिस्से के समान सबसे अधिक उपयोग करते हैं।
ViewModelLocator पहले निर्माण को देखने के लिए एक मानक, सुसंगत, घोषणात्मक और शिथिल युग्मित तरीका प्रदान करता है जो ViewModel को देखने के लिए झुका हुआ होने की प्रक्रिया को स्वचालित करता है। निम्न आंकड़ा ViewModelLocator की उच्च स्तरीय प्रक्रिया का प्रतिनिधित्व करता है।
Step 1 - चित्र देखें कि किस प्रकार का निर्माण किया जा रहा है।
Step 2 - उस विशेष दृश्य प्रकार के लिए ViewModel को पहचानें।
Step 3 - उस ViewModel का निर्माण।
Step 4 - ViewModel के लिए दृश्य DataContext सेट करें।
मूल अवधारणा को समझने के लिए, आइए पिछले अध्याय से एक ही उदाहरण जारी करके ViewModelLocator के सरल उदाहरण पर एक नजर डालते हैं। यदि आप StudentView.xaml फ़ाइल को देखते हैं, तो आप देखेंगे कि हमने सांख्यिकीय रूप से ViewModel को झुका दिया है।
अब जैसा कि निम्नलिखित कार्यक्रम में दिखाया गया है, टिप्पणी करें इन XAML कोड को भी कोड-पीछे से हटा दें।
<UserControl x:Class = "MVVMDemo.Views.StudentView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:MVVMDemo.Views"
xmlns:viewModel = "clr-namespace:MVVMDemo.ViewModel"
mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
<!--<UserControl.DataContext>
<viewModel:StudentViewModel/>
</UserControl.DataContext>-->
<Grid>
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path = Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode = OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
अब एक नया फ़ोल्डर VML बनाते हैं और एक नया सार्वजनिक वर्ग ViewModelLocator जोड़ते हैं जिसमें एक एकल संलग्न गुण (निर्भरता गुण) AutoHookedUpViewModel होगा जैसा कि निम्नलिखित कोड में दिखाया गया है।
public static bool GetAutoHookedUpViewModel(DependencyObject obj) {
return (bool)obj.GetValue(AutoHookedUpViewModelProperty);
}
public static void SetAutoHookedUpViewModel(DependencyObject obj, bool value) {
obj.SetValue(AutoHookedUpViewModelProperty, value);
}
// Using a DependencyProperty as the backing store for AutoHookedUpViewModel.
//This enables animation, styling, binding, etc...
public static readonly DependencyProperty AutoHookedUpViewModelProperty =
DependencyProperty.RegisterAttached("AutoHookedUpViewModel",
typeof(bool), typeof(ViewModelLocator), new PropertyMetadata(false,
AutoHookedUpViewModelChanged));
और अब आप एक मूल अनुलग्नक संपत्ति परिभाषा देख सकते हैं। प्रॉपर्टी में व्यवहार जोड़ने के लिए, हमें इस प्रॉपर्टी के लिए एक बदला हुआ ईवेंट हैंडलर जोड़ना होगा, जिसमें ViewModel for View को हुक करने की स्वचालित प्रक्रिया शामिल है। ऐसा करने के लिए कोड निम्नानुसार है -
private static void AutoHookedUpViewModelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e) {
if (DesignerProperties.GetIsInDesignMode(d)) return;
var viewType = d.GetType();
string str = viewType.FullName;
str = str.Replace(".Views.", ".ViewModel.");
var viewTypeName = str;
var viewModelTypeName = viewTypeName + "Model";
var viewModelType = Type.GetType(viewModelTypeName);
var viewModel = Activator.CreateInstance(viewModelType);
((FrameworkElement)d).DataContext = viewModel;
}
निम्नलिखित ViewModelLocator वर्ग का पूर्ण कार्यान्वयन है।
using System;
using System.ComponentModel;
using System.Windows;
namespace MVVMDemo.VML {
public static class ViewModelLocator {
public static bool GetAutoHookedUpViewModel(DependencyObject obj) {
return (bool)obj.GetValue(AutoHookedUpViewModelProperty);
}
public static void SetAutoHookedUpViewModel(DependencyObject obj, bool value) {
obj.SetValue(AutoHookedUpViewModelProperty, value);
}
// Using a DependencyProperty as the backing store for AutoHookedUpViewModel.
//This enables animation, styling, binding, etc...
public static readonly DependencyProperty AutoHookedUpViewModelProperty =
DependencyProperty.RegisterAttached("AutoHookedUpViewModel",
typeof(bool), typeof(ViewModelLocator), new
PropertyMetadata(false, AutoHookedUpViewModelChanged));
private static void AutoHookedUpViewModelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e) {
if (DesignerProperties.GetIsInDesignMode(d)) return;
var viewType = d.GetType();
string str = viewType.FullName;
str = str.Replace(".Views.", ".ViewModel.");
var viewTypeName = str;
var viewModelTypeName = viewTypeName + "Model";
var viewModelType = Type.GetType(viewModelTypeName);
var viewModel = Activator.CreateInstance(viewModelType);
((FrameworkElement)d).DataContext = viewModel;
}
}
}
पहली बात यह है कि एक नाम स्थान जोड़ना है ताकि हम अपनी परियोजना के मूल में उस ViewModelLocator प्रकार को प्राप्त कर सकें। फिर रूट एलिमेंट पर जो एक व्यू टाइप है, AutoHookedUpViewModel प्रॉपर्टी को जोड़ें और इसे सही पर सेट करें।
xmlns:vml = "clr-namespace:MVVMDemo.VML"
vml:ViewModelLocator.AutoHookedUpViewModel = "True"
यहाँ StudentView.xaml फ़ाइल का पूर्ण कार्यान्वयन है।
<UserControl x:Class = "MVVMDemo.Views.StudentView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:MVVMDemo.Views"
xmlns:viewModel = "clr-namespace:MVVMDemo.ViewModel"
xmlns:vml = "clr-namespace:MVVMDemo.VML"
vml:ViewModelLocator.AutoHookedUpViewModel = "True"
mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
<!--<UserControl.DataContext>
<viewModel:StudentViewModel/>
</UserControl.DataContext>-->
<Grid>
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path = Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode = OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
जब उपरोक्त कोड संकलित और निष्पादित किया जाता है, तो आप देखेंगे कि ViewModelLocator उस विशेष दृश्य के लिए ViewModel को हुक कर रहा है।
इस बारे में ध्यान देने वाली एक महत्वपूर्ण बात यह है कि दृश्य अब एक तरह से युग्मित नहीं है कि इसके व्यूमॉडल का प्रकार क्या है या इसका निर्माण कैसे किया जाता है। यह सब ViewModelLocator के अंदर केंद्रीय स्थान पर ले जाया गया है।