Пробую освоить MVVM, дается очень тяжело. В теории вроде понятно, а вот как на практике реализовать, не очень понимаю. Тем более хочу использовать команды. Делаю простое приложение, два окна - одно основное, и второе. На первом расположена кнопка при нажатии на которую необходимо открыть второе окно-форму, в котором заполняются данные (имя и фамилия), при кнопки Ок - записать все в коллекцию (банально в List), как передать данные в список, то же вопрос. Примерно выглядеть будет так:
Дерево проекта:
Разметка первой вью
<Window x:Class="CommandMVVM.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:CommandMVVM"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid DataContext="{StaticResource MainWindowViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Button Name="v_Button_ToggleNextWindow" Grid.Row="1" Command="{Binding ToggleNextWindowCommand}" VerticalAlignment="Center" Content="Second Window" HorizontalAlignment="Center" Width="90"/>
</Grid>
Вторая вью
<Window x:Class="CommandMVVM.SecondWindow"
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:CommandMVVM"
mc:Ignorable="d"
Title="SecondWindow" Height="450" Width="800">
<Grid DataContext="{StaticResource SecondWindowViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Name="Name" Grid.Row="0" Margin="560,71,10,281" Command="{Binding .....}"/>
<TextBlock Name="LastName" Grid.Row="0" Margin="560,71,10,281" Command="{Binding .....}"/>
<Button Name="v_Button_ToggleNextWindow" Grid.Row="1" Command="{Binding .....}" VerticalAlignment="Center" Content="Ok" HorizontalAlignment="Center" Width="90"/>
</Grid>
Класс реализующий интерфейс комманд
public class DelegateCommand : ICommand
{
private readonly Action _command;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public DelegateCommand(Action command, Func<bool> canExecute = null)
{
if (command == null)
throw new ArgumentNullException();
_canExecute = canExecute;
_command = command;
}
public void Execute(object parameter)
{
_command();
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
}
Класс реализующий INotifyPropertyChanged
public abstract class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
NotifyPropertyChanged(propertyName);
}
}
}
Базовый класс от которого потом наследую ViewModel
public class BaseViewModel : NotificationObject //(реализует INotifyPropertyChanged)
{
}
Ну и сами вьюмодели. Вот в них и не знаю, что необходимо делать...
public class MainWindowViewModel : BaseViewModel
{
}
public class SecondWindowViewModel : BaseViewModel
{
}
В биндинге пока пусто, так как не понимаю, что туда биндить, какой-то Action. Еще один вопрос, если использовать в проекте комманды, использовать события компонентов вью это моветон или нормальная практика?
Проблема в коде вида
DataContext="{StaticResource SecondWindowViewModel}"
Этот код, с одной стороны, противоречит принципам MVVM: окно не имеет права ни создавать, ни выбирать себе VM.
С другой стороны, отвлекаясь от иделогии в практическую сторону, если у вас VM создаются отдельно, у вас нет нормальной возможности связать их между собой. Соответственно передача данных между ними становится сложным заданием.
Я бы предложил воспользоваться идеей отсюда и создавать VM отдельно. Ваш код будет выглядеть как-то так:
<Application x:Class="Namespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- убрал StartupUri -->
</Application>
public partial class App : Application
{
MainWindowViewModel mainVM;
SecondWindowViewModel secondVM;
public App()
{
// тут вы связываете между собой VM, например, так:
mainVM = new MainWindowViewModel();
secondVM = new SecondWindowViewModel(mainVM);
// или наоборот mainVM = new MainWindowViewModel(secondVM)
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
new MainWindow() { DataContext = mainVM }.Show();
}
}
и т. д.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Я хочу реализовать простенький скриптСмысл его заключается в том, чтобы когда вылезает окно с ошибкой на каком-либо сайте моя программа искала...