MVVM Implementing started

This commit is contained in:
2023-03-25 12:34:24 +01:00
parent 47535950b2
commit b1ef5cffb5
36 changed files with 844 additions and 5 deletions

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel
{
public delegate TViewModel CreateViewModel<TViewModel>() where TViewModel : BaseViewModel;
public class BaseViewModel : ObservableObject
{
public virtual void Dispose() { }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel
{
public interface IViewModel : INotifyPropertyChanged
{
}
public interface IViewModel<TModel> : IViewModel
{
[Browsable(false)]
[Bindable(false)]
TModel Model { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using SewerStammGen.Interface.Navigator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel
{
internal class MainWindowViewModel : BaseViewModel
{
public IMainWindowNavigator Navigator { get; set; }
public BaseViewModel CurrentView => Navigator.CurrentViewModel;
public MainWindowViewModel(IMainWindowNavigator navigator)
{
Navigator = navigator;
}
}
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace SewerStammGen.ViewModel
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace SewerStammGen.ViewModel
{
[Serializable]
class RelayCommand : ICommand
{
#region Fields
private readonly Action<object> execute;
private readonly Predicate<object> canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null) throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
#endregion
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
if (canExecute == null) return true;
return canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
execute(parameter);
}
#endregion
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel
{
class SewerConnectorViewModel : ViewModel
{
}
}

View File

@@ -0,0 +1,25 @@
using SewerStammGen.Interface.Navigator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel.State.Navigation
{
internal class MainWindowNavigator : ObservableObject, IMainWindowNavigator
{
private BaseViewModel _currentViewModel;
public BaseViewModel CurrentViewModel
{
get => _currentViewModel;
set
{
_currentViewModel?.Dispose();
_currentViewModel = value;
StateChanged?.Invoke();
}
}
public event Action StateChanged;
}
}

View File

@@ -0,0 +1,179 @@
using Syncfusion.UI.Xaml.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace SewerStammGen.ViewModel
{
[Serializable]
public abstract class ViewModel : IViewModel
{
protected ViewModel()
{
var initializationTask = new Task(() => Initialize());
initializationTask.ContinueWith(result => InitializationCompletedCallback(result));
initializationTask.Start();
}
/// <summary>
/// Initializes this instance.
/// </summary>
protected virtual void Initialize()
{
}
/// <summary>
/// Callback method for the async initialization.
/// </summary>
/// <param name="result">The result.</param>
private void InitializationCompletedCallback(IAsyncResult result)
{
var initializationCompleted = InitializationCompleted;
if (initializationCompleted != null)
{
InitializationCompleted(this, new AsyncCompletedEventArgs(null, !result.IsCompleted, result.AsyncState));
}
InitializationCompleted = null;
}
/// <summary>
/// Occurs when the initialization is completed.
/// </summary>
public event AsyncCompletedEventHandler InitializationCompleted;
/// <summary>
/// Called when a property has changed.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <remarks></remarks>
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property value changes.
/// </summary>
/// <remarks></remarks>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public abstract class ViewModel<TModel> : ViewModel, IViewModel<TModel> where TModel : class
{
private TModel model;
/// <summary>
/// The Model encapsulated by this ViewModel.
/// </summary>
/// <remarks>If you change this, all needed PropertyChanged events will be raised automatically.</remarks>
[Browsable(false)]
[Bindable(false)]
public TModel Model
{
get
{
return model;
}
set
{
if (Model != value)
{
// get all properties
var properties = this.GetType().GetProperties(BindingFlags.Public);
// all values before the model has changed
var oldValues = properties.Select(p => p.GetValue(this, null));
var enumerator = oldValues.GetEnumerator();
model = value;
// call OnPropertyChanged for all changed properties
foreach (var property in properties)
{
enumerator.MoveNext();
var oldValue = enumerator.Current;
var newValue = property.GetValue(this, null);
if ((oldValue == null && newValue != null)
|| (oldValue != null && newValue == null)
|| (!oldValue.Equals(newValue)))
{
OnPropertyChanged(property.Name);
}
}
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ViewModel"/> class.
/// </summary>
/// <remarks></remarks>
protected ViewModel(TModel model)
: base()
{
this.Model = model;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return Model.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (obj == null)
return false;
var other = obj as IViewModel<TModel>;
if (other == null)
return false;
return Equals(other);
}
/// <summary>
/// Determines whether the specified <see cref="IViewModel<TModel>"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="IViewModel<TModel>"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="IViewModel<TModel>"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(IViewModel<TModel> other)
{
if (other == null)
return false;
if (Model == null)
return Model == other.Model;
return Model.Equals(other.Model);
}
}
}