BionicUtilities.Net 1.2.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.2.1
dotnet add package BionicUtilities.Net --version 1.2.1
<PackageReference Include="BionicUtilities.Net" Version="1.2.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BionicUtilities.Net --version 1.2.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

Contains

  • BaseViewModel
  • AsyncRelayCommand&lt;T&gt;
  • Extension Methods for WPF e.g.
    • TryFindVisualParentElement&lt;TParent&gt; : bool
    • TryFindVisualParentElementByName : bool
    • TryFindVisualChildElement&lt;TChild&gt; : bool
    • TryFindVisualChildElementByName : bool
    • FindVisualChildElements&lt;TChildren&gt; : IEnumerable&lt;TChildren&gt;
    • ICollection.AddRange&lt;T&gt;
  • EventArgs
  • ValueConverters
    • BoolToStringConverter
    • BooleanMultiValueConverter
    • FilePathTruncateConverter
    • InvertValueConverter
  • Collections
    • ObservablePropertyChangedCollection&lt;T&gt;
  • MarkupExtensions
    • PrimitiveTypeExtension
  • Profiler
  • AppSettingsConnector - A defaul API to the AppSettings that provides strongly typed reading and writing (e.g. boo, int, double, string) of key-value pair values
  • MruManager - Most Recently Used (MRU) file manager. An API that maintains an MRU table stored in the Application Settings file.

BaseViewModel

implements INotifyPropertyChanged and INotifyDataErrorInfo

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;
}

MRU (Most Recently Used) file manager

The MruManager maintains a collection of MostRecentlyUsedFileItem elrecentlyements that map to a recently used file. Once the max number of recently used files is reached and a new file is added, the MruManager automatically removes the least used file to free the MRU table.

Example: Save file to MRU list

var mruManager = new MruManager();
mruManager.MaxMostRecentlyUsedCount = 30;

var openFileDialog = new OpenFileDialog();
bool? result = openFileDialog.ShowDialog();

// Process open file dialog box results
if (result == true)
{
  string filename = openFileDialog.FileName;

  // Save the picked file in the MRU list
  mruManager.AddMostRecentlyUsedFile(filename);
}
Example: Read file from MRU list

var mruManager = new MruManager();
mruManager.MaxMostRecentlyUsedCount = 30;

MostRecentlyUsedFileItem lastUsedFile = mruManager.MostRecentlyUsedFile;

// Since the list is a ReadOnlyObservableCollection you can directly bind to it 
// and receive CollectionChanged notifications, which will automatically update the binding target
ReadOnlyObservableCollection<MostRecentlyUsedFileItem> mruList = mruManager.MostRecentlyUsedFiles;

BionicUtilities.Net

Reusable utility and class library for WPF.

NuGet package

Class Reference

Contains

  • BaseViewModel
  • AsyncRelayCommand&lt;T&gt;
  • Extension Methods for WPF e.g.
    • TryFindVisualParentElement&lt;TParent&gt; : bool
    • TryFindVisualParentElementByName : bool
    • TryFindVisualChildElement&lt;TChild&gt; : bool
    • TryFindVisualChildElementByName : bool
    • FindVisualChildElements&lt;TChildren&gt; : IEnumerable&lt;TChildren&gt;
    • ICollection.AddRange&lt;T&gt;
  • EventArgs
  • ValueConverters
    • BoolToStringConverter
    • BooleanMultiValueConverter
    • FilePathTruncateConverter
    • InvertValueConverter
  • Collections
    • ObservablePropertyChangedCollection&lt;T&gt;
  • MarkupExtensions
    • PrimitiveTypeExtension
  • Profiler
  • AppSettingsConnector - A defaul API to the AppSettings that provides strongly typed reading and writing (e.g. boo, int, double, string) of key-value pair values
  • MruManager - Most Recently Used (MRU) file manager. An API that maintains an MRU table stored in the Application Settings file.

BaseViewModel

implements INotifyPropertyChanged and INotifyDataErrorInfo

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;
}

MRU (Most Recently Used) file manager

The MruManager maintains a collection of MostRecentlyUsedFileItem elrecentlyements that map to a recently used file. Once the max number of recently used files is reached and a new file is added, the MruManager automatically removes the least used file to free the MRU table.

Example: Save file to MRU list

var mruManager = new MruManager();
mruManager.MaxMostRecentlyUsedCount = 30;

var openFileDialog = new OpenFileDialog();
bool? result = openFileDialog.ShowDialog();

// Process open file dialog box results
if (result == true)
{
  string filename = openFileDialog.FileName;

  // Save the picked file in the MRU list
  mruManager.AddMostRecentlyUsedFile(filename);
}
Example: Read file from MRU list

var mruManager = new MruManager();
mruManager.MaxMostRecentlyUsedCount = 30;

MostRecentlyUsedFileItem lastUsedFile = mruManager.MostRecentlyUsedFile;

// Since the list is a ReadOnlyObservableCollection you can directly bind to it 
// and receive CollectionChanged notifications, which will automatically update the binding target
ReadOnlyObservableCollection<MostRecentlyUsedFileItem> mruList = mruManager.MostRecentlyUsedFiles;

Release Notes

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.

Dependencies

This package has no dependencies.

This package is not used by any popular GitHub repositories.

Version History

Version Downloads Last updated
1.2.1 38 10/18/2019
1.2.0 41 10/13/2019
1.1.13 44 10/12/2019
1.1.12 49 10/3/2019
1.1.11 48 10/3/2019
1.1.10 49 10/3/2019
1.1.9 48 10/3/2019
1.1.8 48 10/3/2019
1.1.7 49 10/3/2019
1.1.6 50 10/3/2019
1.1.5 54 10/1/2019
1.1.4 54 10/1/2019
1.1.0 56 9/29/2019