laatzen/Common/OmniPlus/InspectionUI/ViewModels/VM.cs
2024-09-02 16:24:34 +02:00

139 lines
4.1 KiB
C#

namespace InspectionUI
{
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
/// <summary>
/// Base view model with notification features and commands.
/// </summary>
public abstract class VM : INotifyPropertyChanged, IDisposable
{
private static readonly Dispatcher dispatcher = App.Current.Dispatcher;
private String exception;
private Visibility exceptionVisible;
/// <summary>
/// Should be implemented in order to use Activate and Deactivate events.
/// </summary>
protected VM()
{
App.Activate += this.Activated;
this.ExceptionVisible = Visibility.Collapsed;
this.CloseException = new Command(this.CloseExceptionHanler);
}
public event PropertyChangedEventHandler PropertyChanged;
public String Exception
{
get => this.exception;
protected set => this.Set(() => this.exception = value);
}
public Visibility ExceptionVisible
{
get => this.exceptionVisible;
protected set => this.Set(() => this.exceptionVisible = value);
}
public ICommand CloseException { get; }
/// <summary>
/// Should be the last call when overriden
/// </summary>
public virtual void Dispose()
{
App.Activate -= this.Activated;
App.Deactivate -= this.Dispose;
}
protected void DispatcherInvoke(Action action)
{
try
{
dispatcher.Invoke(action);
}
catch (Exception e)
{
this.Exception = e.ToString();
}
}
/// <summary>
/// Should be the first call when overriden
/// </summary>
protected virtual void Activated() => App.Deactivate += this.Dispose;
protected void NotifyPropertyChanged([CallerMemberName] String property = "")
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
protected void Set(Action setExpression, [CallerMemberName] String property = "")
{
this.DispatcherInvoke(setExpression);
this.NotifyPropertyChanged(property);
}
protected void StartTask(Action action)
{
Task.Factory
.StartNew(action)
.ContinueWith(this.Catch);
}
protected void Catch(Task task)
{
if (task.Exception != null)
{
this.Exception = task.Exception.ToString();
this.ExceptionVisible = Visibility.Visible;
}
}
private void CloseExceptionHanler()
{
this.Exception = null;
this.ExceptionVisible = Visibility.Collapsed;
}
protected class Command : ICommand
{
private readonly Action executable;
public Command(Action executable) => this.executable = executable;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(Object _) => this.executable != null;
public void Execute(Object _) => this.executable?.Invoke();
}
protected class Command<T> : ICommand
{
private readonly Action<T> executable;
public Command(Action<T> executable) => this.executable = executable;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(Object _) => this.executable != null;
public void Execute(Object parameter) => this.executable?.Invoke(parameter is T t ? t : default(T));
}
}
}