Presentation is loading. Please wait.

Presentation is loading. Please wait.

Arkitektur, klasser og ansvar

Similar presentations


Presentation on theme: "Arkitektur, klasser og ansvar"— Presentation transcript:

1 Arkitektur, klasser og ansvar
MVVM Starter Arkitektur, klasser og ansvar

2 Arkitektur

3 App View View Model Validators Controllers Filters Model

4 View XAML Bruger-interaktion Bindings Kontakt til ViewModel
Ingen kontakt til Model MVVMStarter: skabelon til Master/Details view Studerende: Et view for hver domæne-klasse View

5 View Model C# Udstiller properties som Views kan binde til
Transformationer fra domæne- objekter til ViewModel-objekter Kontakt til Model MVVMStarter: Base-klasser Studerende: ~5 (små) klasser per domæne-klasse View Model

6 Model C# Singleton-adgang til collection af domæne-objekter
Kontakt til source for objekter MVVMStarter: Base-klasser Studerende: To (små) klasser per domæne-klasse Model

7 App C# Overordnet navigation Konfiguration Fil-persistens
MVVMStarter: Veldefinerede entry-points for nye domæne- klasser Studerende: <5 (små) tilføjelser ved entry-points App

8 Validators Validering på property-niveau int: interval
string: længde, indeholder MVVMStarter: statiske metoder for generisk validering, præsen- tation med undo-funktion Studerende: Afhængig af krav til validering Validators

9 Controllers Controllers out-of-the-box for CRUD-operationer
Aktiveres via Commands Meget små (<5 linjer C#) MVVMStarter: Controllers kan tilføjes/overrides Studerende: Afhængig af krav til forretningslogik Controllers

10 Filters Muligt at addere et antal filtre til et Catalog.
Filter: domæne-objekt -> bool Filtre kan programmatisk slås til og fra MVVMStarter: Generiske Filter og FilterManager klasser Studerende: Afhængig af krav til forretningslogik Filters

11 Model

12 Properties af simple typer (int, string,…) Kan tilføjes validering
Egen domæne-klasse Properties af simple typer (int, string,…) Kan tilføjes validering Car

13 Car public class Car { public string LicensePlate { get; set; }
// …etc }

14 Car : DomainClassBase public class Car : DomainClassBase {
public string LicensePlate { get; set; } // …etc public override void SetDefaultValues() LicensePlate = "(not set)"; } Car : DomainClassBase

15 DomainClassBase public abstract class DomainClassBase {
public int Key {…} protected DomainClassBase() SetDefaultValues(); } public abstract void SetDefaultValues(); public virtual DomainClassBase Clone() return (DomainClassBase)MemberwiseClone(); DomainClassBase

16 Rummer en collection af domæne-objekter Fil-baseret persistens (JSON)
Load- og Save-metoder Metoder for operationer på collection (Insert, Delete, …) Catalog CollectionBase<Car> Car FileSourceBase<Car> CarModel.dat

17 CollectionBase<Car> Car
Catalog CollectionBase<Car> Car public class Catalog : CatalogBase<Car> { // Generic singleton code private Catalog() : base(new CollectionBase<Car>(), new FileSourceBase<Car>()) } FileSourceBase<Car> CarModel.dat

18 CollectionBase<TDomainClass>
public class CollectionBase<TDomainClass> { private Dictionary<int, TDomainClass> _collection; public List<TDomainClass> All {…} public void Insert(TDomainClass obj) {…} public bool Delete(int key) {…} public void DeleteAll() {…} // plus key management } Dictionary<int, TDomainClass>

19 FileSourceBase<TDomainClass>
public class FileSourceBase<TDomainClass> : SourceBase<TDomainClass> { public CollectionBase<TDomainClass> Load() {…} public void Save(CollectionBase<TDomainClass> coll) } CarModel.dat (JSON)

20 CatalogBase<TDomainClass>
CollectionBase<TDomainClass> public class CatalogBase<TDomainClass> { public List<TDomainClass> All {…} public void Insert(TDomainClass obj) {…} public bool Delete(int key) {…} public void DeleteAll() {…} public bool Modified {…} public void Load() {…} public void Save() {…} } FileSourceBase<TDomainClass>

21 ViewModel

22 View Location Berlin AX In EU now Yes Create Update Delete Read

23 <Grid> <StackPanel> <StackPanel> <StackPanel>
<Image> <TextBlock> <TextBlock> <TextBox> <StackPanel> <Button> <StackPanel> <RadioButton>

24 MasterDetails ViewModel Master ViewModel Details ViewModel Item ViewModel Commands (actions) Commands (states)

25 MasterDetails ViewModel Master ViewModel Details ViewModel Item ViewModel Catalog CollectionBase<Car> Car

26 Item ViewModel Details ViewModel ItemPropertyA ItemPropertyB ItemPropertyC DetailsPropertyA DetailsPropertyB DetailsPropertyC Car Car

27 Collection<ItemViewModel>
Master ViewModel ItemViewModel CreateItemViewModel(Car obj) Catalog CollectionBase<Car> Car

28 CatalogBase<Car>
MasterDetails ViewModel ViewModel Factory Master ViewModel Item ViewModel Details ViewModel Create() Create(Car obj) Create(Car obj) CatalogBase<Car> CollectionBase<Car> obj Car

29 ItemViewModelCollection ItemViewModelSelected ItemSelectorEnabled
<Page> DataContext = MasterDetailsViewModel <Grid> MasterDetails ViewModel <ListView> ItemViewModelCollection ItemViewModelSelected ItemSelectorEnabled ItemSelectorVisible <StackPanel> DetailsViewModelSelected ViewControlStates

30 View MasterDetails ViewModel Master Details CreateCommand UpdateCommand DeleteCommand Commands (actions) ViewControlStates SelectCreateCommand SelectReadCommand SelectUpdateCommand SelectDeleteCommand Commands (state)

31 Objekt vil referere til et enkelt domæne-objekt
ItemViewModelBase<Car> Definition af, hvorledes et domæne-objekt præsenterer sig i en liste-orienteret GUI kontrol (f.eks. ListView) Objekt vil referere til et enkelt domæne-objekt Et antal virtuelle properties kan overrides Item ViewModel FontSize ImageIsVisible ImageSize Car Description ImageSource

32 ItemViewModelBase<Car>
<StackPanel> Item ViewModel <Image> <TextBlock> FontSize ImageIsVisible ImageSize public override int FontSize { get { return 24; } } public override string ImageSource get { return DomainObject.PhotoSource; } public ItemViewModel(Car obj) DomainObject = obj; Car Description ImageSource

33 ItemViewModelBase<Car>
<StackPanel> Item ViewModel <Image> <TextBlock> FontSize ImageIsVisible ImageSize <ListView.ItemTemplate> <DataTemplate DataType="ItemViewModel"> <StackPanel Orientation="Horizontal"> <Image Source="{Binding ImageSource}" Visibility="{Binding ImageVisibility}" Width="{Binding ImageSize}" Height="{Binding ImageSize}" /> <TextBlock Text="{Binding Description}" FontSize="{Binding FontSize} /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> Car Description ImageSource

34 Objekt vil referere til et enkelt domæne-objekt
DetailsViewModelBase<Car> Definition af, hvorledes data fra et domæne-objekt skal præsenteres i et Details-view Objekt vil referere til et enkelt domæne-objekt Simple properties: en-til-en mapping til properties på domæne-objekt (get/set) Aggregerede (beregnede) properties: Kun get Details ViewModel Car Location SimplePropB SimplePropC InEU AggrPropB Location SimplePropB SimplePropC

35 DetailsViewModelBase<Car> Location
In EU now Details ViewModel Car public string Location { get { return DomainObject.Location; } set DomainObject.Location = value; OnPropertyChanged(); } public string InEU get { return DomainObject.InEU(DomainObject.Location); } // …etc public DetailsViewModel(Car obj) DomainObject = obj; Location SimplePropB SimplePropC InEU AggrPropB Location SimplePropB SimplePropC

36 DetailsViewModelBase<Car> Location {Binding …}
In EU now Details ViewModel Car <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding …}"/> <TextBox IsEnabled="{Binding …}” Visibility="{Binding …}" Text="{Binding DetailsViewModel.Location, Mode=TwoWay}" /> </StackPanel> Text="{Binding DetailsViewModel.InEU, Mode=OneWay}" /> Location SimplePropB SimplePropC InEU AggrPropB Location SimplePropB SimplePropC

37 Transformation af en collection af domæne- objekter til en collection af ItemViewModel-objekter
Transformation af det enkelte domæne-objekt er defineret i ItemViewModel MasterViewModelBase<Car> Master ViewModel

38 MasterViewModelBase<Car>
public class MasterViewModel() : MasterViewModelBase<Car> { } Master ViewModel public virtual List<ItemViewModel> CreateItemVMCollection( CatalogBase<Car> catalog, ViewModelFactoryBase<Car> factory) { _itemViewModelCollection.Clear(); foreach (Car obj in catalog.All) _itemViewModelCollection.Add(factory.CreateItemVM(obj)); } return _itemViewModelCollection;

39 ListView MasterDetails ViewModel Master ViewModel ItemVMC
public List<ItemViewModel> ItemViewModelCollection { get return _masterVM.CreateItemVMCollection( _catalog, _viewModelFactory); } ViewModel Factory ItemVMC Master ViewModel Catalog Car CreateItemVMC(catalog, factory) public virtual List<ItemViewModel> CreateItemVMCollection( CatalogBase<Car> catalog, ViewModelFactoryBase<Car> factory) { _itemViewModelCollection.Clear(); foreach (Car obj in catalog.All) _itemViewModelCollection.Add(factory.CreateItemVM(obj)); } return _itemViewModelCollection; List<ItemViewModel> List<ItemViewModel>

40 Holder sammen på alle ViewModel-objekter
MasterDetails ViewModel Holder sammen på alle ViewModel-objekter Udstiller properties, som View kan binde sig til Bliver DataContext for View

41 MasterDetails ViewModel
public class MasterDetailsViewModel() : MasterDetailsViewModelBase<Car> { public MasterDetailsViewModel() : base(new ViewModelFactory(), Models.Domain.Car.Catalog.Instance) StateManager.AddViewControlState(…); // …etc }

42 View

43 View Location Berlin AX In EU now Yes Create Update Delete Read

44 <Page> <Grid> <StackPanel> <StackPanel>
<Image> <TextBlock> <TextBlock> <TextBox> <StackPanel> <Button> <StackPanel> <RadioButton>

45 <Page> <Grid> MasterDetails ViewModel Details Master
<Page.DataContext> <MasterDetailsViewModel> </Page.DataContext> <Page.Resources ...> <Grid> <!-- (Master) --> <ListView ...> <!-- (Details) --> <StackPanel ...> <!-- (Action buttons) --> <!-- (State buttons) --> </Grid> <Page> <Grid> Details Master Action buttons State buttons MasterDetails ViewModel

46 <ListView> MasterDetails ViewModel Master ViewModel Item
ItemsSource="{Binding ItemViewModelCollection}" SelectedItem="{Binding ItemViewModelSelected, Mode=TwoWay}" Visibility="{Binding ItemSelectorVisible}" IsEnabled="{Binding ItemSelectorEnabled}" > <ListView.ItemTemplate ...> </ListView> MasterDetails ViewModel Master ViewModel Item ViewModel

47 Item ViewModel <ListView.ItemTemplate>
<DataTemplate DataType="ItemViewModel"> <StackPanel Orientation="Horizontal"> <Image Source="{Binding ImageSource}" Visibility="{Binding ImageVisibility}" Width="{Binding ImageSize}" Height="{Binding ImageSize}" /> <TextBlock Text="{Binding Description}" FontSize="{Binding FontSize} /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> Item ViewModel

48 <StackPanel> <StackPanel> MasterDetails ViewModel Details
... <StackPanel Orientation="Horizontal"> <TextBlock Style="{StaticResource TextBlockStyle}" Text="{Binding ViewControlStates[Location].Description}"/> <TextBox Style="{StaticResource TextBoxStyle}" IsEnabled="{Binding ViewControlStates[Location].Enabled}" Visibility="{Binding ViewControlStates[Location].Visible}" Text="{Binding DetailsViewModel.Location, Mode=TwoWay}"/> </StackPanel> MasterDetails ViewModel Details ViewModel

49 <StackPanel> MasterDetails ViewModel <Button>
... <!--Delete button--> <Button Content="Delete" Style="{StaticResource ButtonStyle}" IsEnabled="{Binding ViewControlStates[Delete].Enabled}" Visibility="{Binding ViewControlStates[Delete].Visible}" Command="{Binding DeleteCommand}"/> </StackPanel> <StackPanel> <Button> MasterDetails ViewModel

50 <StackPanel> MasterDetails ViewModel <StackPanel> ...
<!--Create radiobutton--> <RadioButton Content=“Create" Style ="{StaticResource RadioButtonStyle}" Command ="{Binding SelectCreateCommand}"/> </StackPanel> <StackPanel> <RadioButton> MasterDetails ViewModel

51 Validering

52 View Model Validators Validation Exception Model

53 Car : DomainClassBase public class Car : DomainClassBase {
public string LicensePlate { get; set; } // …etc } Car : DomainClassBase

54 Car ValidationHandler public class Car : DomainClassBase {
private string _licensePlate; public string LicensePlate get { return licensePlate; } set ValidationHandler.ThrowOnInvalid<string>( Validator.ValidateLicensePlate, value); _licensePlate = value; } Car public static void ThrowOnInvalid<TValue>( Func<TValue,ValidationOutcome> validator, TValue value) { ValidationOutcome vo = validator(value); if (vo != null) throw new ValidationException(vo.Message); } ValidationHandler

55 Car Validator (in Domain.Car) ValidatorHandler set {
ValidationHandler.ThrowOnInvalid<string>( Validator.ValidateLicensePlate, value); _licensePlate = value; } Car public static ValidationOutcome ValidateLicensePlate(string value) { return ValidationHandler.ValidateStringMinLength(value, 3); } Validator (in Domain.Car) public static ValidationOutcome ValidateStringMinLength( string value, int minLength, [CallerMemberName] string propertyName = null) { string message = propertyName + " " + " must contain at least " + minLength + " characters"; return Validate<string>(value, (v => v.Length >= minLength), message); } ValidatorHandler

56 Details ViewModel Car public string LicensePlate {
get { return DomainObject.LicensePlate; } set DomainObject.LicensePlate = value; OnPropertyChanged(); } Car

57 Details ViewModel Car public string LicensePlate {
get { return DomainObject.LicensePlate; } set try DomainObject.LicensePlate = value; } catch (ValidationException e) PresentValidationError(e.Message, () => { OnPropertyChanged(); }); OnPropertyChanged(); Details ViewModel Car protected void PresentValidationError(string message, Action undo) { UserActionPresenter.PresentMessage( message, "Undo", new RelayCommand(undo)); }

58 License plate AX

59 throw new ValidationException(…)
MasterDetails ViewModel Details ViewModel Model Car License plate AX 43 52 set try { DomainObject.LicensePlate = value; } set get set { ValidationHandler.ThrowOnInvalid<string>( Validator.ValidateLicensePlate, value); _licensePlate = value; } throw new ValidationException(…) catch (ValidationException e) { PresentValidationError( e.Message, () => { OnPropertyChanged(); }); } Undo OnPropertyChanged()

60 throw ValidationException
MasterDetails ViewModel Details ViewModel Model Car License plate AX get throw ValidationException Undo OnPropertyChanged()

61 Controllers

62 View Action View Model Controllers Model

63 ICommand ControllerBase<TDomainClass>
public abstract class ControllerBase<TDomainClass> : ICommand { MasterDetailsViewModelBase<TDomainClass> MasterDetailsViewModel; CatalogBase<TDomainClass> Catalog; // etc. } public abstract void Execute(); ControllerBase<TDomainClass>

64 ICommand DeleteControllerBase<TDomainClass>
public override void Execute() { TDomainClass obj = MasterDetailsViewModel.ItemViewModel.DomainObject; Catalog.Delete(obj.Key); MasterDetailsViewModel.AfterModelDelete(obj); } DeleteControllerBase<TDomainClass>

65 AfterModelDelete(key)
Controller MasterDetails ViewModel Model Delete(key) AfterModelDelete(key) public virtual void AfterModelDelete(int key) { ItemViewModelSelected = null; OnPropertyChanged(nameof(ItemViewModelCollection)); } get public List<ItemViewModel> ItemViewModelCollection { get return _masterVM.CreateItemViewModelCollection( _catalog, _viewModelFactory); }

66 MasterDetails ViewModel Delete
private ControllerBase<TDomainClass> _deleteCommandController; _deleteCommandController = new DeleteControllerBase<TDomainClass>(this, _catalog); public ICommand DeleteCommand { get { return _deleteCommandController; } } Delete

67 MasterDetails ViewModel Delete Controller Delete
<Button Content="Delete" Style="{…}" IsEnabled="{Binding …}" Visibility="{Binding …}" Command="{Binding DeleteCommand}"/> Delete Controller Execute Delete

68 Filters

69 Filter Filter Filter Catalog CollectionBase<Car> Car Car
Condition Filter Condition Filter Condition Car

70 CollectionBase<Car> Car
Catalog public class Catalog : CatalogBase<Car> { public Filter<Car> PriceFilter; private bool PriceCondition(Car obj) return obj.Price < ; } ... private Catalog() : base(...) PriceFilter = new Filter<Car>("PriceFilter", PriceCondition); AddFilter(PriceFilter); CollectionBase<Car> Car Filter

71 MasterDetails ViewModel public bool PriceFilterOn {
get { return CarCatalog.Instance.PriceFilter.On; } set CarCatalog.Instance.PriceFilter.On = value; OnPropertyChanged(nameof(ItemViewModelCollection)); } StateManager.AddViewControlState(new ViewControlState( "PriceFilter", "Price below 100k"));

72 View MasterDetails ViewModel
<TextBlock Text="{Binding ViewControlStates[PriceFilter].Description}"/> <ToggleSwitch IsOn="{Binding PriceFilterOn, Mode=TwoWay}"/> MasterDetails ViewModel

73 Udvidelser

74 Cross-domain logik Cross-property validering Database (Entity Framework) integration Web-services / Cloud Run-time konfiguration af views (show/hide Master…) Auto-generering af kode


Download ppt "Arkitektur, klasser og ansvar"

Similar presentations


Ads by Google