BionicUtilities.Net 1.4.1

Reusable utility and class library for WPF - Featuring: AsyncRelayCommand<T>, ObservablePropertyChangedCollection, BaseViewModel, Visual Tree Helpers, Profiling, Extension Methods, ValueChangedEventArgs, MruManager (Most Recently Used files), AppSettingsConnector and more.

Install-Package BionicUtilities.Net -Version 1.4.1
dotnet add package BionicUtilities.Net --version 1.4.1
<PackageReference Include="BionicUtilities.Net" Version="1.4.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BionicUtilities.Net --version 1.4.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

BionicUtilities.Net

Reusable utility and class library for WPF.

NuGet package

Class Reference

GitHub

Contains (snippet - full read me here)

(Click class link to load example)

BaseViewModel

  • Implements and encapsulates INotifyPropertyChanged and INotifyDataErrorInfo.
  • Allows to control whether invalid data is set on a property or neglected until validation passes by setting the default parameter isRejectInvalidValueEnabled of TrySetValue() to true (neglects invalid values by default).
  • Also allows to control whether to throw an exception on validation error or not (silent) by setting the default parameter isThrowExceptionOnValidationErrorEnabled of TrySetValue() to true (is silent by default).
  • Additionally exposes a PropertyValueChanged event which is raised in tandem with INotifyPropertyChanged.PropertyChanged but additionally carries old value and new value as event args.
Example with validation
private string name;
public string Name
{
  get => this.name;
  set
  {
    if (TrySetValue(
      value,
      (stringValue) =>
      {
        var messages = new List<string>() {"Name must start with an underscore"};
        return (stringValue.StartsWith("_"), messages);
      },
      ref this.name))
    {
      DoSomething(this.name);
    }
  }
}
Example without validation
private string name;
public string Name
{
  get => this.name;
  set
  {
    if (TrySetValue(value, ref this.name))
    {
      DoSomething(this.name);
    }
  }
}

AsyncRelayComand&lt;T&gt;

Reusable generic command class that encapsulates ICommand and allows asynchronous execution.
When used with a Binding the command will execute asynchronously when an awaitable execute handler is assigned to the command.

Example
// ICommand property
public IAsyncRelayCommand<string> StringAsyncCommand => new AsyncRelayCommand<string>(ProcessStringAsync);
    
// Execute asynchronously
await StringAsyncCommand.ExecuteAsync("String value");
    
// Execute synchronously
StringAsyncCommand.Execute("String value");
    

Profiler

Static helper methods to measure performance e.g. the execution time of a code portion.

Example
// Specify a custom output
Profiler.LogPrinter = (timeSpan) => PrintToFile(timeSpan);
    
// Measure the average execution time of a specified number of iterations.
TimeSpan elapsedTime = Profiler.LogAverageTime(() => ReadFromDatabase(), 1000);
    
// Measure the execution times of a specified number of iterations.
List<TimeSpan> elapsedTime = Profiler.LogTimes(() => ReadFromDatabase(), 1000);
    
// Measure the execution time.
TimeSpan elapsedTime = Profiler.LogTime(() => ReadFromDatabase());

ValueChangedEventArgs&lt;T&gt;

Generic EventArgs implementation that provides value change information like OldValue and NewValue.

Example
// Specify a named ValueTuple as event argument
event EventHandler<ValueChangedEventArgs<(bool HasError, string Message)>> Completed;    
    
protected virtual void RaiseCompleted((bool HasError, string Message) oldValue, (bool HasError, string Message) newValue)
{
  this.Completed?.Invoke(this, new ValueChangedEventArgs<(bool HasError, string Message)>(oldValue, newValue));
}

private void OnCompleted(object sender, ValueChangedEventArgs<(bool HasError, string Message)> e)
{
  (bool HasError, string Message) newValue = e.NewValue;
  if (newValue.HasError)
  {
    this.TaskCompletionSource.TrySetException(new InvalidOperationException(newValue.Message));
  }
  this.TaskCompletionSource.TrySetResult(true);
}

AppSettingsConnector

A static default API to the AppSettings that provides strongly typed reading and writing (e.g. boo, int, double, string) of key-value pair values.

Example
// Write the Most Recently Used file count to the AppSettings file
AppSettingsConnector.WriteInt("mruCount", 10);

// If key exists read the Most Recently Used file count from the AppSettings file
if (TryReadInt("mruCount", out int mruCount))
{
  this.MruCount = mruCount;
}

GitHub (full read me here)

BionicUtilities.Net

Reusable utility and class library for WPF.

NuGet package

Class Reference

GitHub

Contains (snippet - full read me here)

(Click class link to load example)

BaseViewModel

  • Implements and encapsulates INotifyPropertyChanged and INotifyDataErrorInfo.
  • Allows to control whether invalid data is set on a property or neglected until validation passes by setting the default parameter isRejectInvalidValueEnabled of TrySetValue() to true (neglects invalid values by default).
  • Also allows to control whether to throw an exception on validation error or not (silent) by setting the default parameter isThrowExceptionOnValidationErrorEnabled of TrySetValue() to true (is silent by default).
  • Additionally exposes a PropertyValueChanged event which is raised in tandem with INotifyPropertyChanged.PropertyChanged but additionally carries old value and new value as event args.
Example with validation
private string name;
public string Name
{
  get => this.name;
  set
  {
    if (TrySetValue(
      value,
      (stringValue) =>
      {
        var messages = new List<string>() {"Name must start with an underscore"};
        return (stringValue.StartsWith("_"), messages);
      },
      ref this.name))
    {
      DoSomething(this.name);
    }
  }
}
Example without validation
private string name;
public string Name
{
  get => this.name;
  set
  {
    if (TrySetValue(value, ref this.name))
    {
      DoSomething(this.name);
    }
  }
}

AsyncRelayComand&lt;T&gt;

Reusable generic command class that encapsulates ICommand and allows asynchronous execution.
When used with a Binding the command will execute asynchronously when an awaitable execute handler is assigned to the command.

Example
// ICommand property
public IAsyncRelayCommand<string> StringAsyncCommand => new AsyncRelayCommand<string>(ProcessStringAsync);
    
// Execute asynchronously
await StringAsyncCommand.ExecuteAsync("String value");
    
// Execute synchronously
StringAsyncCommand.Execute("String value");
    

Profiler

Static helper methods to measure performance e.g. the execution time of a code portion.

Example
// Specify a custom output
Profiler.LogPrinter = (timeSpan) => PrintToFile(timeSpan);
    
// Measure the average execution time of a specified number of iterations.
TimeSpan elapsedTime = Profiler.LogAverageTime(() => ReadFromDatabase(), 1000);
    
// Measure the execution times of a specified number of iterations.
List<TimeSpan> elapsedTime = Profiler.LogTimes(() => ReadFromDatabase(), 1000);
    
// Measure the execution time.
TimeSpan elapsedTime = Profiler.LogTime(() => ReadFromDatabase());

ValueChangedEventArgs&lt;T&gt;

Generic EventArgs implementation that provides value change information like OldValue and NewValue.

Example
// Specify a named ValueTuple as event argument
event EventHandler<ValueChangedEventArgs<(bool HasError, string Message)>> Completed;    
    
protected virtual void RaiseCompleted((bool HasError, string Message) oldValue, (bool HasError, string Message) newValue)
{
  this.Completed?.Invoke(this, new ValueChangedEventArgs<(bool HasError, string Message)>(oldValue, newValue));
}

private void OnCompleted(object sender, ValueChangedEventArgs<(bool HasError, string Message)> e)
{
  (bool HasError, string Message) newValue = e.NewValue;
  if (newValue.HasError)
  {
    this.TaskCompletionSource.TrySetException(new InvalidOperationException(newValue.Message));
  }
  this.TaskCompletionSource.TrySetResult(true);
}

AppSettingsConnector

A static default API to the AppSettings that provides strongly typed reading and writing (e.g. boo, int, double, string) of key-value pair values.

Example
// Write the Most Recently Used file count to the AppSettings file
AppSettingsConnector.WriteInt("mruCount", 10);

// If key exists read the Most Recently Used file count from the AppSettings file
if (TryReadInt("mruCount", out int mruCount))
{
  this.MruCount = mruCount;
}

GitHub (full read me here)

Release Notes

- Fixed AsyncRelayCommand when using no param overload of CanExecute()
   - Added dynamic multitype EventAggregator
   - Added PropertyValueChanged event to BaseViewModel
   - Added MVVM conform display dialog infrastructure
   
   ---------------------------------------------------------
   For bug reports or feature requests please visit the project home on GutHub (follow the "Project Site" link on the right) and then open an issue (open the "issue" tab, click "New Issue" and select the appropriate template) or send  a mail to BionicCode@outlook.com. Thank you very much.

This package is not used by any popular GitHub repositories.

Version History

Version Downloads Last updated
1.4.1 88 12/4/2019
1.2.1 81 10/18/2019
1.2.0 78 10/13/2019
1.1.13 80 10/12/2019
1.1.12 100 10/3/2019
1.1.11 97 10/3/2019
1.1.10 99 10/3/2019
1.1.9 98 10/3/2019
1.1.8 96 10/3/2019
1.1.7 98 10/3/2019
1.1.6 91 10/3/2019
1.1.5 93 10/1/2019
1.1.4 94 10/1/2019
1.1.0 94 9/29/2019