|  | @@ -0,0 +1,445 @@
 | 
	
		
			
				|  |  | +using Comal.Classes;
 | 
	
		
			
				|  |  | +using InABox.Clients;
 | 
	
		
			
				|  |  | +using InABox.Core;
 | 
	
		
			
				|  |  | +using InABox.DynamicGrid;
 | 
	
		
			
				|  |  | +using InABox.WPF;
 | 
	
		
			
				|  |  | +using Syncfusion.Data;
 | 
	
		
			
				|  |  | +using Syncfusion.UI.Xaml.Grid;
 | 
	
		
			
				|  |  | +using Syncfusion.Windows.Shared;
 | 
	
		
			
				|  |  | +using System;
 | 
	
		
			
				|  |  | +using System.Collections;
 | 
	
		
			
				|  |  | +using System.Collections.Generic;
 | 
	
		
			
				|  |  | +using System.ComponentModel;
 | 
	
		
			
				|  |  | +using System.Data;
 | 
	
		
			
				|  |  | +using System.Linq;
 | 
	
		
			
				|  |  | +using System.Runtime.CompilerServices;
 | 
	
		
			
				|  |  | +using System.Text;
 | 
	
		
			
				|  |  | +using System.Threading.Tasks;
 | 
	
		
			
				|  |  | +using System.Windows;
 | 
	
		
			
				|  |  | +using System.Windows.Controls;
 | 
	
		
			
				|  |  | +using System.Windows.Data;
 | 
	
		
			
				|  |  | +using System.Windows.Media;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace PRSDesktop.Panels.Reservation_Management;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class JobRequisitionItemSelectionItem : BaseObject
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    public double Quantity { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private double _issued;
 | 
	
		
			
				|  |  | +    public double Issued
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        get => _issued;
 | 
	
		
			
				|  |  | +        set
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var oldValue = _issued;
 | 
	
		
			
				|  |  | +            var canMinus = CanMinus;
 | 
	
		
			
				|  |  | +            var canPlus = CanPlus;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            _issued = value;
 | 
	
		
			
				|  |  | +            if(oldValue != value)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(Issued), oldValue, value);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(canMinus != CanMinus)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(CanMinus), canMinus, CanMinus);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(canPlus != CanPlus)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(CanPlus), canPlus, CanPlus);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public double MaxValue { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private bool _editable = true;
 | 
	
		
			
				|  |  | +    public bool Editable
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        get => _editable;
 | 
	
		
			
				|  |  | +        set
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var oldValue = _editable;
 | 
	
		
			
				|  |  | +            var canMinus = CanMinus;
 | 
	
		
			
				|  |  | +            var canPlus = CanPlus;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            _editable = value;
 | 
	
		
			
				|  |  | +            if(oldValue != value)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(Editable), oldValue, value);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(canMinus != CanMinus)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(CanMinus), canMinus, CanMinus);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(canPlus != CanPlus)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                OnPropertyChanged(nameof(CanPlus), canPlus, CanPlus);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public bool CanMinus => Editable && Issued > 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public bool CanPlus => Editable && Issued < MaxValue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public JobRequisitionItem JRI { get; set; }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public abstract class JobRequisitionItemSelectionGrid<T> : DynamicItemsListGrid<T>, INotifyPropertyChanged
 | 
	
		
			
				|  |  | +    where T : JobRequisitionItemSelectionItem, new()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    private double _totalQuantity;
 | 
	
		
			
				|  |  | +    public double TotalQuantity
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        get => _totalQuantity;
 | 
	
		
			
				|  |  | +        set
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            _totalQuantity = value;
 | 
	
		
			
				|  |  | +            OnPropertyChanged();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private double _totalIssued;
 | 
	
		
			
				|  |  | +    public double TotalIssued
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        get => _totalIssued;
 | 
	
		
			
				|  |  | +        set
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            _totalIssued = value;
 | 
	
		
			
				|  |  | +            OnPropertyChanged();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private bool _observing = true;
 | 
	
		
			
				|  |  | +    public void SetObserving(bool observing)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if(_observing != observing)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            _observing = observing;
 | 
	
		
			
				|  |  | +            if (_observing)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Recalculate();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected override void Init()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        base.Init();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicTemplateColumn(TotalColumn_Template)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HeaderText = "Total",
 | 
	
		
			
				|  |  | +            Width = 60,
 | 
	
		
			
				|  |  | +            GetSummary = () =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var summary = new GridSummaryColumn
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    TemplateSelector = new FuncTemplateSelector((item, o) => TotalQuantity_Template())
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                return summary;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicTemplateColumn(QuantityColumn_Template)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HeaderText = "Quantity",
 | 
	
		
			
				|  |  | +            Width = 230,
 | 
	
		
			
				|  |  | +            GetSummary = () =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var summary = new GridSummaryColumn
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    TemplateSelector = new FuncTemplateSelector((item, o) => TotalIssued_Template())
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                return summary;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected override void DoReconfigure(DynamicGridOptions options)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        base.DoReconfigure(options);
 | 
	
		
			
				|  |  | +        options.Clear();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FrameworkElement TotalQuantity_Template()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var quantity = new DoubleTextBox
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HorizontalContentAlignment = HorizontalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalContentAlignment = VerticalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalAlignment = VerticalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            HorizontalAlignment = HorizontalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            Background = new SolidColorBrush(Colors.WhiteSmoke),
 | 
	
		
			
				|  |  | +            IsReadOnly = true,
 | 
	
		
			
				|  |  | +            Margin = new Thickness(0, 5, 0, 5)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        quantity.Bind(DoubleTextBox.ValueProperty, this, x => x.TotalQuantity);
 | 
	
		
			
				|  |  | +        return quantity;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FrameworkElement TotalIssued_Template()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var quantity = new DoubleTextBox
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HorizontalContentAlignment = HorizontalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalContentAlignment = VerticalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalAlignment = VerticalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            HorizontalAlignment = HorizontalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            Background = new SolidColorBrush(Colors.LightGreen),
 | 
	
		
			
				|  |  | +            IsReadOnly = true,
 | 
	
		
			
				|  |  | +            Margin = new Thickness(50 + 30 + 10, 5, 50 + 30 + 5, 5)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        quantity.Bind(DoubleTextBox.ValueProperty, this, x => x.TotalIssued);
 | 
	
		
			
				|  |  | +        return quantity;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private class TotalAggregate : ISummaryAggregate
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public double Sum { get; private set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private JobRequisitionItemSelectionGrid<T> Grid;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public enum TotalColumn
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Quantity,
 | 
	
		
			
				|  |  | +            Issued
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public TotalColumn Type { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public TotalAggregate(TotalColumn type, JobRequisitionItemSelectionGrid<T> grid)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Type = type;
 | 
	
		
			
				|  |  | +            Grid = grid;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public Action<IEnumerable, string, PropertyDescriptor> CalculateAggregateFunc()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return AggregateFunc;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private void AggregateFunc(IEnumerable items, string property, PropertyDescriptor args)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (items is IEnumerable<DataRowView> rows)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Sum = Type switch
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    TotalColumn.Quantity => Grid.TotalQuantity,
 | 
	
		
			
				|  |  | +                    TotalColumn.Issued or _ => Grid.TotalIssued
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Logger.Send(LogType.Error, "", $"Attempting to calculate aggregate on invalid data type '{items.GetType()}'.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private class UIComponent : DynamicGridGridUIComponent<T>
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public UIComponent(JobRequisitionItemSelectionGrid<T> grid)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Parent = grid;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            GridLines = DynamicGridLines.None;
 | 
	
		
			
				|  |  | +            RowHeight = 40;
 | 
	
		
			
				|  |  | +            HeaderRowHeight = 40;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override Brush? GetCellSelectionBackgroundBrush()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        protected override Brush? GetCellSelectionForegroundBrush()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return base.GetCellBackground(row, column);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override Style GetHeaderCellStyle(DynamicColumnBase column)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var style = base.GetHeaderCellStyle(column);
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Silver)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.Bold));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0.0)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0.0)));
 | 
	
		
			
				|  |  | +            return style;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override Style GetSummaryRowStyle()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var style = base.GetSummaryRowStyle();
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BorderBrushProperty, new SolidColorBrush(Colors.Silver)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(1, 1, 0, 1)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0, 1, 0, 0)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.WhiteSmoke)));
 | 
	
		
			
				|  |  | +            return style;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override Style GetSummaryCellStyle(DynamicColumnBase column)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var style = base.GetSummaryCellStyle(column);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(GridTableSummaryCell.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch));
 | 
	
		
			
				|  |  | +            style.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(0)));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return style;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected override IDynamicGridUIComponent<T> CreateUIComponent()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return new UIComponent(this);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FrameworkElement? TotalColumn_Template(CoreRow row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var item = LoadItem(row);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var quantity = new DoubleTextBox
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HorizontalContentAlignment = HorizontalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalContentAlignment = VerticalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalAlignment = VerticalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            Background = new SolidColorBrush(Colors.WhiteSmoke),
 | 
	
		
			
				|  |  | +            IsReadOnly = true,
 | 
	
		
			
				|  |  | +            Margin = new Thickness(0, 5, 0, 5)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        quantity.Bind(DoubleTextBox.ValueProperty, item, x => x.Quantity);
 | 
	
		
			
				|  |  | +        quantity.Bind(Button.IsEnabledProperty, item, x => x.Editable);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return quantity;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FrameworkElement? QuantityColumn_Template(CoreRow row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var item = LoadItem(row);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var grid = new Grid();
 | 
	
		
			
				|  |  | +        grid.Margin = new Thickness(5);
 | 
	
		
			
				|  |  | +        grid.AddColumn(50);
 | 
	
		
			
				|  |  | +        grid.AddColumn(30);
 | 
	
		
			
				|  |  | +        grid.AddColumn(60);
 | 
	
		
			
				|  |  | +        grid.AddColumn(30);
 | 
	
		
			
				|  |  | +        grid.AddColumn(50);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var none = new Button
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Content = "None",
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        none.Bind(Button.IsEnabledProperty, item, x => x.Editable);
 | 
	
		
			
				|  |  | +        none.Margin = new Thickness(0);
 | 
	
		
			
				|  |  | +        none.Click += (o, e) => None_Click(item);
 | 
	
		
			
				|  |  | +        grid.AddChild(none, 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var minus = new Button
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Content = "-",
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        minus.Bind(Button.IsEnabledProperty, item, x => x.CanMinus);
 | 
	
		
			
				|  |  | +        minus.Margin = new Thickness(5, 0, 0, 0);
 | 
	
		
			
				|  |  | +        minus.Click += (o, e) => Minus_Click(item);
 | 
	
		
			
				|  |  | +        grid.AddChild(minus, 0, 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var quantity = new DoubleTextBox
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            HorizontalContentAlignment = HorizontalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalContentAlignment = VerticalAlignment.Center,
 | 
	
		
			
				|  |  | +            VerticalAlignment = VerticalAlignment.Stretch,
 | 
	
		
			
				|  |  | +            Background = new SolidColorBrush(Colors.LightYellow),
 | 
	
		
			
				|  |  | +            Margin = new Thickness(5, 0, 0, 0)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        quantity.Bind(DoubleTextBox.ValueProperty, item, x => x.Issued);
 | 
	
		
			
				|  |  | +        quantity.MinValue = 0;
 | 
	
		
			
				|  |  | +        quantity.Bind(DoubleTextBox.MaxValueProperty, item, x => x.MaxValue);
 | 
	
		
			
				|  |  | +        quantity.Bind(Button.IsEnabledProperty, item, x => x.Editable);
 | 
	
		
			
				|  |  | +        grid.AddChild(quantity, 0, 2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var plus = new Button
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Content = "+",
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        plus.Bind(Button.IsEnabledProperty, item, x => x.CanPlus);
 | 
	
		
			
				|  |  | +        plus.Margin = new Thickness(5, 0, 0, 0);
 | 
	
		
			
				|  |  | +        plus.Click += (o, e) => Plus_Click(item);
 | 
	
		
			
				|  |  | +        grid.AddChild(plus, 0, 3);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var all = new Button
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Content = "All",
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        all.Bind(Button.IsEnabledProperty, item, x => x.Editable);
 | 
	
		
			
				|  |  | +        all.Margin = new Thickness(5, 0, 0, 0);
 | 
	
		
			
				|  |  | +        all.Click += (o, e) => All_Click(item);
 | 
	
		
			
				|  |  | +        grid.AddChild(all, 0, 4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return grid;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void None_Click(T item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        item.Issued = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void Minus_Click(T item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        item.Issued = Math.Max(0, item.Issued - 1);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void Plus_Click(T item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if(item.JRI.ID == Guid.Empty)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            item.Issued += 1;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            item.Issued = Math.Min(item.Issued + 1, item.Quantity);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void All_Click(T item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        item.Issued = Math.Max(0, item.Quantity);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected override void Reload(Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sort, Action<CoreTable?, Exception?> action)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        foreach(var item in Items)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            item.PropertyChanged += (o, e) => Recalculate();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        Recalculate();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        base.Reload(criteria, columns, ref sort, action);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Dictionary<Guid, double> GetQuantities()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return Items.ToDictionary(x => x.JRI.ID, x => x.Issued);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    private void Recalculate()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (!_observing) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        TotalQuantity = Items.Sum(x => x.Quantity);
 | 
	
		
			
				|  |  | +        TotalIssued = Items.Sum(x => x.Issued);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public event PropertyChangedEventHandler? PropertyChanged;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |