|
|||||||
Реализация MVVM. ViewModel
Время создания: 01.01.2020 21:14
Раздел: Компьютер - C# - WPF - MVVM - Metanit
Запись: Kozlov-AE/Tetra/master/base/1577902453k143zdm6rc/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Для работы с паттерном MVVM создадим новый проект. По умолчанию в проект добавляется стартовое окно MainWindow - это и будет представление. И теперь нам нужна модель и ViewModel. Добавим в проект новый класс Phone, который и будет представлять модель приложения: using System.ComponentModel; using System.Runtime.CompilerServices;
namespace MVVM { public class Phone : INotifyPropertyChanged { private string title; private string company; private int price;
public string Title { get { return title; } set { title = value; OnPropertyChanged("Title"); } } public string Company { get { return company; } set { company = value; OnPropertyChanged("Company"); } } public int Price { get { return price; } set { price = value; OnPropertyChanged("Price"); } }
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } } Для уведомления системы об изменениях свойств модель Phone реализует интерфейс INotifyPropertyChanged. Хотя в рамках паттерна MVVM это необязательно. В других конструкция и ситуациях все может быть определено иначе. Также добавим в проект новый класс ApplicationViewModel, который будет представлять модель представления: using System.ComponentModel; using System.Runtime.CompilerServices; using System.Collections.ObjectModel;
namespace MVVM { public class ApplicationViewModel : INotifyPropertyChanged { private Phone selectedPhone;
public ObservableCollection<Phone> Phones { get; set; } public Phone SelectedPhone { get { return selectedPhone; } set { selectedPhone = value; OnPropertyChanged("SelectedPhone"); } }
public ApplicationViewModel() { Phones = new ObservableCollection<Phone> { new Phone { Title="iPhone 7", Company="Apple", Price=56000 }, new Phone {Title="Galaxy S7 Edge", Company="Samsung", Price =60000 }, new Phone {Title="Elite x3", Company="HP", Price=56000 }, new Phone {Title="Mi5S", Company="Xiaomi", Price=35000 } }; }
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } } Это класс модели представления, через который будут связаны модель Phone и представление MainWindow.xaml. В этом классе определен список объектов Phone и свойство, которое указывает на выделенный элемент в этом списке. В итоге веcь проект будет выглядеть следующим образом: Далее изменим код нашего представления - файла MainWindow.xaml: <Window x:Class="MVVM.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MVVM" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="14" /> </Style> <Style TargetType="TextBox"> <Setter Property="FontSize" Value="14" /> </Style> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="0.8*" /> </Grid.ColumnDefinitions>
<ListBox Grid.Column="0" ItemsSource="{Binding Phones}" SelectedItem="{Binding SelectedPhone}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="5"> <TextBlock FontSize="18" Text="{Binding Path=Title}" /> <TextBlock Text="{Binding Path=Company}" /> <TextBlock Text="{Binding Path=Price}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
<StackPanel Grid.Column="1" DataContext="{Binding SelectedPhone}"> <TextBlock Text="Выбранный элемент" /> <TextBlock Text="Модель" /> <TextBox Text="{Binding Title, UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Text="Производитель" /> <TextBox Text="{Binding Company, UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Text="Цена" /> <TextBox Text="{Binding Price, UpdateSourceTrigger=PropertyChanged}" /> </StackPanel> </Grid> </Window> Здесь определен элемент ListBox, который привязан к свойству Phones объекта ApplicationViewModel, а также определен набор элементов, которые привязаны к свойствам объекта Phone, выделенного в ListBox. И изменим файл кода MainWindow.xaml.cs: using System.Windows;
namespace MVVM { public partial class MainWindow : Window { public MainWindow() { InitializeComponent();
DataContext = new ApplicationViewModel(); } } } Здесь достаточно установить контекст данных для данного окна в виде объекта ApplicationViewModel, который свяжет представление и модели Phone. И если мы запустим приложение, то увидим список объектов. Мы можем выбрать один из них, и его данные появятся в полях справа: При этом на не надо определять код загрузки объектов в ListBox, определять обработчики выбора объекта в списке или сохранения его данных. За нас все делает механизм привязки данных. Определение модели В данном случае мы сами определяем модель Phone. Однако не всегда мы имеем возможность реализовать в используемой модели интерфейс INotifyPropertyChanged. Также, возможно, мы захотим предусмотреть отдельное представление (отдельное окно) для манипуляций над одной моделью (добавление, изменение, удаление). Подобное представление может иметь в качестве ViewModel объект модели Phone. И в подобных случаях мы можем создать отдельную ViewModel для работы с одним объектом Phone, наподобие: using System.ComponentModel; using System.Runtime.CompilerServices;
namespace MVVM { public class PhoneViewModel : INotifyPropertyChanged { private Phone phone;
public PhoneViewModel(Phone p) { phone = p; }
public string Title { get { return phone.Title; } set { phone.Title = value; OnPropertyChanged("Title"); } } public string Company { get { return phone.Company; } set { phone.Company = value; OnPropertyChanged("Company"); } } public int Price { get { return phone.Price; } set { phone.Price = value; OnPropertyChanged("Price"); } }
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } } |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|