MVVM - ViewModel Bağlanıyor

Bu bölümde, ViewModel'in nasıl bağlanacağını ele alacağız. Bu, View ilk yapısını tartıştığımız son bölümün devamıdır. Şimdi, ilk yapının bir sonraki şekli birmeta-pattern olarak bilinen ViewModelLocator. Sözde bir modeldir ve MVVM modelinin üstüne katmanlanmıştır.

  • MVVM'de her Görünümün kendi ViewModel'ine bağlanması gerekir.

  • ViewModelLocator, kodu merkezileştirmek ve görünümü daha fazla ayırmak için basit bir yaklaşımdır.

  • Bu, ViewModel türü ve nasıl inşa edileceği hakkında açıkça bilgi sahibi olmak zorunda olmadığı anlamına gelir.

  • ViewModelLocator'ı kullanmak için bir dizi farklı yaklaşım vardır, ancak burada PRISM çerçevesinin parçası olana en benzer olanı kullanıyoruz.

ViewModelLocator, ViewModel'in View'e bağlanma sürecini otomatikleştiren ilk yapıyı görüntülemek için standart, tutarlı, bildirimsel ve gevşek bir şekilde bağlı bir yol sağlar. Aşağıdaki şekil, ViewModelLocator'ın üst düzey sürecini temsil etmektedir.

Step 1 - Hangi Görünüm türünün oluşturulmakta olduğunu öğrenin.

Step 2 - Söz konusu Görünüm tipi için ViewModel'i tanımlayın.

Step 3 - Bu ViewModel'i oluşturun.

Step 4 - View DataContext'i ViewModel olarak ayarlayın.

Temel kavramı anlamak için, son bölümden aynı örneğe devam ederek basit ViewModelLocator örneğine bakalım. StudentView.xaml dosyasına bakarsanız, ViewModel'i statik olarak bağladığımızı göreceksiniz.

Şimdi, aşağıdaki programda gösterildiği gibi, bu XAML kodunu yorumlayın ve kodu arka planda koddan kaldırın.

<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>

Şimdi yeni bir klasör VML oluşturalım ve aşağıdaki kodda gösterildiği gibi tek bir ekli özellik (bağımlılık özelliği) içeren yeni bir genel sınıf ViewModelLocator ekleyelim. 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));

Ve şimdi temel bir ekleme özelliği tanımını görebilirsiniz. Özelliğe davranış eklemek için, bu özellik için ViewModel'i View için otomatik olarak bağlama işlemini içeren değiştirilmiş bir olay işleyicisi eklememiz gerekir. Bunu yapacak kod aşağıdaki gibidir -

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; 
}

Aşağıda ViewModelLocator sınıfının tam uygulaması verilmiştir.

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; 
      } 
   } 
}

Yapılacak ilk şey, projemizin kök dizininde o ViewModelLocator türüne ulaşabilmemiz için bir ad alanı eklemektir. Daha sonra bir görünüm türü olan yönlendirme öğesinde, AutoHookedUpViewModel özelliğini ekleyin ve bunu true olarak ayarlayın.

xmlns:vml = "clr-namespace:MVVMDemo.VML"
vml:ViewModelLocator.AutoHookedUpViewModel = "True"

İşte StudentView.xaml dosyasının tam uygulaması.

<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>

Yukarıdaki kod derlendiğinde ve yürütüldüğünde, ViewModelLocator'ın söz konusu View için ViewModel'i bağladığını göreceksiniz.

Bununla ilgili dikkat edilmesi gereken en önemli şey, görünümün artık ViewModel'in türünün ne olduğu veya nasıl inşa edildiğiyle bağlantılı olmamasıdır. Hepsi ViewModelLocator içindeki merkezi konuma taşındı.