First, my advice, forget the Russian names of variables, projects, etc. That's not right.namespace ШаблонMVVM.Model!About MVM, what do we need to know the main? Well, for starters what it's used for. It is used to separate everything and all layers:Model - Your data.View - What the user sees.ViewModel - A sort of connecting layer that helps collect all one whole, so we're describing the logic for View, taking data from the Model and other benefits.Here, you should remember a few more things:From Model and ViewModel, you should not be able to interact with data in View layer (i.e., MyTextBox1.Text = "Hello!" MVM is not appropriate! View should only know that in a ViewModel there may be a certain characteristic Text from which it should take the text for Control'a. This characteristic may not be (renamed, renamed), View will be rudely speaking, nothing will fall and everything will be literate (except for natural value). In other words, our interface does not depend on the code, which, for example, allows for the development of two different teams of interfaces and codes on their own, or the modification of the interface by removing the unnecessary elements (without touching the code). That's the point of splitting everything by layer.Each Model/ViewModel should be responsible for its own, one. Example: For example, we have a student who has some books, a student is some ViewModel with his data set (name, list of books, team (read, give) and other information related only to him), a book is another object that must also have everything that is related to her (e.g., author, date of issue where it is). I mean, you don't have to have that ViewModel is responsible for the books or vice versa! Okay, let's write a simple app now:Establish 3 folders Model, ViewModel and View.In View, we move MainWindow (with all its guts, we don't forget to change all the paths).Create three classes in the director of ViewModel:BaseVM - some class that will be implemented INotifyPropertyChanged♪ What is this all about? For example, we've tied a certain characteristic to the textBox, with the change of this characteristic in the interface code, we're not gonna know about it and not update the data. This is the message that exists in INPC. The reality of this class on the Internet of the ear, I personally use this:public class BaseVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
NotifyPropertyChanged(propertyName);
return true;
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
RelayCommand - Since our View should be independent of ViewModel, we cannot simply use Click and other events (although in some cases it is considered acceptable). Here's a team coming to help us, we build the character of this team and we're tied up, and even if it doesn't, our program won't fall and work properly. Like VM, on the Internet, the ear reality, the most common I think. https://metanit.com/sharp/wpf/22.3.php But I'll take another option again:public class RelayCommand<T> : ICommand
{
private Action<T> action;
public RelayCommand(Action<T> action) => this.action = action;
public bool CanExecute(object parameter) => true;
#pragma warning disable CS0067
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
public void Execute(object parameter) => action((T)parameter);
}
public class RelayCommand : ICommand
{
private Action action;
public RelayCommand(Action action) => this.action = action;
public bool CanExecute(object parameter) => true;
#pragma warning disable CS0067
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
public void Execute(object parameter) => action();
}
MainViewModel - This is our main VM. I won't describe the code until we've just created an empty class.Now let's get DataContext. Honestly, I don't get the right thing to do, one good man remembers by his hand... for telling the DataContext in the XAML, and I've recently read, and at all, it's better to get him to a higher level. That's why I'm here to use the App.We're at App.xaml. StartupUri="MainWindow.xaml" And we'll sign up there on Startup.We'll take out the variables of our window ( private MainWindow MainWindow;♪In a studio-based method (signature on Startup event) we need to initiate our MainViewModel and put it in the window, and naturally show it:private void App_OnStartup(object sender, StartupEventArgs e)
{
var mainViewModel = new MainViewModel();
MainWindow = new MainWindow { DataContext = mainViewModel };
MainWindow.Show();
}
That's what you're saying, we've got an old-fashioned template, and only logic to write.Best example of how to interact:Give the Model a model that will give data. Let's call her Student.public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Student[] GetStudents()
{
var result = new[]
{
new Student{FirstName = "Маша", LastName = "Иванова"},
new Student{FirstName = "Витя", LastName = "Егоров"},
new Student{FirstName = "Женя", LastName = "Петров"}
};
return result;
}
}
Next, we're gonna need a ViewModel of our student, we're gonna create, it's got the necessary logic for a student:public class StudentViewModel : BaseVM
{
public StudentViewModel(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
RenameCommand = new RelayCommand<string>(Rename);
}
private string firstName;
public string FirstName
{
get => firstName;
set => Set(ref firstName, value);
}
private string lastName;
public string LastName
{
get => lastName;
set => Set(ref lastName, value);
}
public ICommand RenameCommand { get; set; }
private void Rename(string name)
{
FirstName = name;
}
}
Let's unite this in MainViewModel:public class MainViewModel
{
public ObservableCollection<StudentViewModel> Students { get; set; }
private Student StudentData;
public MainViewModel()
{
StudentData = new Student();
Students = new ObservableCollection<StudentViewModel>();
LoadData();
}
private void LoadData()
{
foreach (var student in StudentData.GetStudents())
Students.Add(new StudentViewModel(student.FirstName, student.LastName));
}
}
We have to write a simple View:<ItemsControl ItemsSource="{Binding Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding FirstName}" Margin="0,0,5,0"/>
<TextBlock Grid.Column="1" Text="{Binding LastName}" Margin="0,0,5,0"/>
<TextBox Grid.Column="2" Name="changeText" Margin="0,0,5,0"/>
<Button Grid.Column="3" Content="Изменить" Command="{Binding RenameCommand}" CommandParameter="{Binding ElementName=changeText, Path=Text}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
That's it, let's start and check: I may not have precision here, but I think you'll understand.Also, as the @tym32167 was correct, there's no universal template for you to do, every project has its own nuances, thinness. In some projects, such an approach would not be appropriate (where there might be the best use of side-offs (where) https://github.com/lbugnion/mvvmlight ; https://caliburnmicro.com ; https://github.com/PrismLibrary/Prism () To facilitate all of this, and where there will be enough, everything depends on the objectives and the project, but to understand how this works, I think my answer will be enough for you.Good luck studying!