MVVM - Wydarzenia
Zdarzenie to konstrukcja programistyczna, która reaguje na zmianę stanu, powiadamiając o wszystkich punktach końcowych zarejestrowanych w celu powiadamiania. Przede wszystkim zdarzenia służą do informowania użytkownika o wejściu za pomocą myszy i klawiatury, ale ich przydatność nie ogranicza się do tego. Za każdym razem, gdy zostanie wykryta zmiana stanu, na przykład po załadowaniu lub zainicjowaniu obiektu, można wywołać zdarzenie w celu ostrzeżenia wszystkich zainteresowanych stron trzecich.
W aplikacji WPF, która używa wzorca projektowego MVVM (Model-View-ViewModel), model widoku jest składnikiem odpowiedzialnym za obsługę logiki i stanu prezentacji aplikacji.
Plik związany z kodem widoku nie powinien zawierać kodu do obsługi zdarzeń, które są wywoływane z dowolnego elementu interfejsu użytkownika (UI), takiego jak Button lub ComboBox, ani nie powinien zawierać żadnej logiki specyficznej dla domeny.
Idealnie byłoby, gdyby kod związany z View zawierał tylko konstruktora, który wywołuje metodę InitializeComponent i być może jakiś dodatkowy kod do kontrolowania lub interakcji z warstwą widoku, która jest trudna lub nieefektywna do wyrażenia w XAML, np. Złożone animacje.
Przyjrzyjmy się prostemu przykładowi zdarzeń kliknięcia przycisku w naszej aplikacji. Poniżej znajduje się kod XAML pliku MainWindow.xaml, w którym zobaczysz dwa przyciski.
<Window x:Class = "MVVMHierarchiesDemo.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:MVVMHierarchiesDemo"
xmlns:views = "clr-namespace:MVVMHierarchiesDemo.Views"
xmlns:viewModels = "clr-namespace:MVVMHierarchiesDemo.ViewModel"
mc:Ignorable = "d"
Title = "MainWindow" Height = "350" Width = "525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType = "{x:Type viewModels:CustomerListViewModel}">
<views:CustomerListView/>
</DataTemplate>
<DataTemplate DataType = "{x:Type viewModels:OrderViewModel}">
<views:OrderView/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<Grid x:Name = "NavBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "*" />
<ColumnDefinition Width = "*" />
<ColumnDefinition Width = "*" />
</Grid.ColumnDefinitions>
<Button Content = "Customers"
Command = "{Binding NavCommand}"
CommandParameter = "customers"
Grid.Column = "0" />
<Button Content = "Order"
Command = "{Binding NavCommand}"
CommandParameter = "orders"
Grid.Column = "2" />
</Grid>
<Grid x:Name = "MainContent" Grid.Row = "1">
<ContentControl Content = "{Binding CurrentViewModel}" />
</Grid>
</Grid>
</Window>
Widać, że właściwość Click przycisku nie jest używana w powyższym pliku XAML, ale właściwości Command i CommandParameter są używane do ładowania różnych widoków po naciśnięciu przycisku. Teraz musisz zdefiniować implementację poleceń w pliku MainWindowViewModel.cs, ale nie w pliku widoku. Poniżej znajduje się pełna implementacja MainWindowViewModel.
using MVVMHierarchiesDemo.ViewModel;
using MVVMHierarchiesDemo.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMHierarchiesDemo {
class MainWindowViewModel : BindableBase {
public MainWindowViewModel() {
NavCommand = new MyICommand<string>(OnNav);
}
private CustomerListViewModel custListViewModel = new CustomerListViewModel();
private OrderViewModel orderViewModelModel = new OrderViewModel();
private BindableBase _CurrentViewModel;
public BindableBase CurrentViewModel {
get { return _CurrentViewModel; }
set { SetProperty(ref _CurrentViewModel, value); }
}
public MyICommand<string> NavCommand { get; private set; }
private void OnNav(string destination) {
switch (destination) {
case "orders":
CurrentViewModel = orderViewModelModel;
break;
case "customers":
default:
CurrentViewModel = custListViewModel;
break;
}
}
}
}
Wyprowadź wszystkie ViewModels z klasy BindableBase. Gdy powyższy kod zostanie skompilowany i wykonany, zobaczysz następujące dane wyjściowe.
Jak widać, dodaliśmy tylko dwa przyciski i CurrentViewModel w naszym MainWindow. Teraz, jeśli klikniesz dowolny przycisk, przejdzie do tego konkretnego widoku. Kliknijmy przycisk Klienci, a zobaczysz, że wyświetla się CustomerListView.
Zalecamy wykonanie powyższego przykładu metodą krok po kroku w celu lepszego zrozumienia.