< Summary

Information
Class: MyNet.UI.ViewModels.Export.ExportViewModelBase<T>
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Export/ExportViewModelBase.cs
Tag: 323_28699572109
Line coverage
100%
Covered lines: 26
Uncovered lines: 0
Coverable lines: 26
Total lines: 126
Line coverage: 100%
Branch coverage
83%
Covered branches: 10
Total branches: 12
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%22100%
set_ExportItemCount(...)100%11100%
get_Errors()100%22100%
get_HasErrors()100%11100%
Load(...)100%11100%
SaveConfiguration()100%11100%
ExportAndCloseAsync()87.5%88100%
Cancel()100%11100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Export/ExportViewModelBase.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="ExportViewModelBase.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System.Collections.Generic;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using System.Windows.Input;
 11using FluentValidation;
 12using MyNet.Observable;
 13using MyNet.Observable.Behaviors;
 14using MyNet.UI.Commands;
 15using MyNet.UI.Notifications;
 16using MyNet.UI.ViewModels.Dialog;
 17
 18namespace MyNet.UI.ViewModels.Export;
 19
 20/// <summary>
 21/// Provides a reusable base implementation for export dialogs.
 22/// </summary>
 23/// <typeparam name="T">The exported item type.</typeparam>
 24public abstract class ExportViewModelBase<T> : DialogViewModel<bool>
 25{
 26    private readonly INotificationPublisher? _notificationPublisher;
 27    private ICollection<T>? _items;
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="ExportViewModelBase{T}"/> class.
 31    /// </summary>
 32    /// <param name="notificationPublisher">Optional notification publisher used to display validation/export errors.</p
 33    /// <param name="commandFactory">Optional command factory used to create commands.</param>
 34    /// <param name="validator">Optional validator used to validate this view model.</param>
 35    protected ExportViewModelBase(
 36        INotificationPublisher? notificationPublisher = null,
 37        ICommandFactory? commandFactory = null,
 38        IValidator? validator = null)
 1239        : base(commandFactory)
 40    {
 1241        _notificationPublisher = notificationPublisher;
 42        ExportAndCloseCommand = Commands.Create(() => ExportAndCloseAsync());
 1243        CancelCommand = Commands.Create(Cancel);
 44
 1245        this.UseTracking()
 1246            .UseValidation(validator ?? new ExportViewModelValidator<T>());
 1247    }
 48
 49    /// <summary>
 50    /// Gets or sets a value indicating whether configuration should be saved before export.
 51    /// </summary>
 1252    public bool SaveConfigurationOnValidate { get; set; } = true;
 53
 54    /// <summary>
 55    /// Gets the number of items loaded for export.
 56    /// </summary>
 957    public int ExportItemCount { get; private set => SetProperty(ref field, value); }
 58
 59    /// <summary>
 60    /// Gets validation error messages from the registered <see cref="IValidationBehavior"/>.
 61    /// </summary>
 62    public IReadOnlyCollection<string> Errors =>
 2763        Behaviors.TryGet<IValidationBehavior>(out var behavior) ? behavior.Errors : [];
 64
 65    /// <summary>
 66    /// Gets a value indicating whether <see cref="Errors"/> contains at least one message.
 67    /// </summary>
 1568    public bool HasErrors => Errors.Count > 0;
 69
 70    /// <summary>
 71    /// Gets the command that exports and closes the dialog.
 72    /// </summary>
 73    public ICommand ExportAndCloseCommand { get; }
 74
 75    /// <summary>
 76    /// Gets the command that cancels the dialog.
 77    /// </summary>
 78    public ICommand CancelCommand { get; }
 79
 80    /// <summary>
 81    /// Loads items to export.
 82    /// </summary>
 83    /// <param name="items">The items to export.</param>
 84    public virtual void Load(ICollection<T> items)
 85    {
 986        _items = items;
 987        ExportItemCount = items.Count;
 988    }
 89
 90    /// <summary>
 91    /// Saves the current export configuration.
 92    /// </summary>
 93    protected virtual void SaveConfiguration()
 94    {
 695    }
 96
 97    /// <summary>
 98    /// Exports provided items.
 99    /// </summary>
 100    /// <param name="items">The items to export.</param>
 101    /// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
 102    /// <returns><see langword="true"/> when export succeeds; otherwise <see langword="false"/>.</returns>
 103    protected abstract Task<bool> ExportItemsAsync(ICollection<T> items, CancellationToken cancellationToken = default);
 104
 105    private async Task ExportAndCloseAsync(CancellationToken cancellationToken = default)
 106    {
 9107        if (!this.TryValidateAndNotify(_notificationPublisher))
 3108            return;
 109
 6110        if (SaveConfigurationOnValidate)
 6111            SaveConfiguration();
 112
 6113        var items = _items ?? [];
 6114        var success = await ExportItemsAsync(items, cancellationToken).ConfigureAwait(false);
 115
 6116        if (success)
 3117            Close(true);
 9118    }
 119
 120    private void Cancel()
 121    {
 3122        SetCancelled();
 3123        RequestClose();
 3124    }
 125}
 126