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(); } /// /// Initializes this instance. /// protected virtual void Initialize() { } /// /// Callback method for the async initialization. /// /// The result. private void InitializationCompletedCallback(IAsyncResult result) { var initializationCompleted = InitializationCompleted; if (initializationCompleted != null) { InitializationCompleted(this, new AsyncCompletedEventArgs(null, !result.IsCompleted, result.AsyncState)); } InitializationCompleted = null; } /// /// Occurs when the initialization is completed. /// public event AsyncCompletedEventHandler InitializationCompleted; /// /// Called when a property has changed. /// /// Name of the property. /// protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #region INotifyPropertyChanged Members /// /// Occurs when a property value changes. /// /// public event PropertyChangedEventHandler PropertyChanged; #endregion } public abstract class ViewModel : ViewModel, IViewModel where TModel : class { private TModel model; /// /// The Model encapsulated by this ViewModel. /// /// If you change this, all needed PropertyChanged events will be raised automatically. [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); } } } } } /// /// Initializes a new instance of the class. /// /// protected ViewModel(TModel model) : base() { this.Model = model; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return Model.GetHashCode(); } /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (obj == null) return false; var other = obj as IViewModel; if (other == null) return false; return Equals(other); } /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public bool Equals(IViewModel other) { if (other == null) return false; if (Model == null) return Model == other.Model; return Model.Equals(other.Model); } } }