MyTetra Share
Делитесь знаниями!
Реализация 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));

        }

    }

}






Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования