using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; using Tango.PPC.Common; using Tango.PPC.Jobs.Messages; using System.Data.Entity; using Tango.Core.Commands; using System.Windows; using Tango.Touch.Controls; using System.Windows.Media; using Tango.DragAndDrop; using System.ComponentModel; using System.Windows.Data; using Tango.PPC.Jobs.Dialogs; using Tango.PPC.Jobs.Views; using Tango.BL.Catalogs; using System.Runtime.InteropServices; using System.Threading; using Tango.BL.ColorConversion; using Tango.SharedUI.Helpers; using Tango.PPC.Common.Navigation; using Tango.PPC.Jobs.NavigationObjects; using Tango.PPC.Jobs.ViewContracts; using System.Collections.ObjectModel; using Tango.PPC.Common.Models; using Tango.Logging; using Tango.PPC.Common.Messages; using Tango.BL.Builders; namespace Tango.PPC.Jobs.ViewModels { /// /// Represents the selected job view model. /// /// public class JobViewVM : PPCViewModel, INavigationObjectReceiver { private ObservablesContext _db; private bool _can_navigate_back; private Thread _check_gamut_thread; private Job _job_to_load; private JobNavigationIntent _job_to_load_intent; private static Dictionary> _jobs_fine_tune_items; #region Properties private Job _job; /// /// Gets or sets the selected job. /// public Job Job { get { return _job; } set { _job = value; RaisePropertyChangedAuto(); } } private ICollectionView _segmentsCollectionView; /// /// Gets or sets the job segments collection view. /// public ICollectionView SegmentsCollectionView { get { return _segmentsCollectionView; } set { _segmentsCollectionView = value; RaisePropertyChangedAuto(); } } private List _colorSpaces; /// /// Gets or sets the available color spaces. /// public List ColorSpaces { get { return _colorSpaces; } set { _colorSpaces = value; RaisePropertyChangedAuto(); } } private List _rmls; /// /// Gets or sets the available RMLS. /// public List Rmls { get { return _rmls; } set { _rmls = value; RaisePropertyChangedAuto(); } } private List _spoolTypes; /// /// Gets or sets the available spool types. /// public List SpoolTypes { get { return _spoolTypes; } set { _spoolTypes = value; RaisePropertyChangedAuto(); } } private List _customers; /// /// Gets or sets the available customers. /// public List Customers { get { return _customers; } set { _customers = value; RaisePropertyChangedAuto(); } } private String _customersFilter; /// /// Gets or sets the customers filter. /// public String CustomersFilter { get { return _customersFilter; } set { _customersFilter = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the customers automatic complete provider. /// public AutoCompleteProvider CustomersAutoCompleteProvider { get; set; } private ObservableCollection _fineTuneItems; /// /// Gets or sets the fine tune items. /// public ObservableCollection FineTuneItems { get { return _fineTuneItems; } set { _fineTuneItems = value; RaisePropertyChangedAuto(); } } private ObservableCollection _approvalFineTuneItems; /// /// Gets or sets the fine tune items. /// public ObservableCollection ApprovalFineTuneItems { get { return _approvalFineTuneItems; } set { _approvalFineTuneItems = value; RaisePropertyChangedAuto(); } } private bool _isFineTuneExpanded; /// /// Gets or sets a value indicating whether the fine tuning region is expanded. /// public bool IsFineTuneExpanded { get { return _isFineTuneExpanded; } set { _isFineTuneExpanded = value; RaisePropertyChangedAuto(); if (_isFineTuneExpanded) { SyncFineTuneItemsToBrushStops(); } } } #endregion #region Commands /// /// Gets or sets the add solid segment command. /// public RelayCommand AddSolidSegmentCommand { get; set; } /// /// Gets or sets the add gradient segment command. /// public RelayCommand AddGradientSegmentCommand { get; set; } /// /// Gets or sets the add brush stop command. /// public RelayCommand AddBrushStopCommand { get; set; } /// /// Gets or sets the segment dropped command. /// public RelayCommand SegmentDroppedCommand { get; set; } /// /// Gets or sets the remove segment command. /// public RelayCommand RemoveSegmentCommand { get; set; } /// /// Gets or sets the remove brush stop command. /// public RelayCommand RemoveBrushStopCommand { get; set; } /// /// Gets or sets the remove job command. /// public RelayCommand RemoveJobCommand { get; set; } /// /// Gets or sets the save job command. /// public RelayCommand SaveJobCommand { get; set; } /// /// Gets or sets the replace brush stop command. /// public RelayCommand ReplaceBrushStopCommand { get; set; } /// /// Gets or sets the twine catalog field tap command. /// public RelayCommand TwineCatalogFieldTapCommand { get; set; } /// /// Gets or sets the increase decrease samples to dye command. /// public RelayCommand IncreaseDecreaseSamplesToDyeCommand { get; set; } /// /// Gets or sets the start sample dye command. /// public RelayCommand StartSampleDyeCommand { get; set; } /// /// Gets or sets the dye command. /// public RelayCommand DyeCommand { get; set; } /// /// Gets or sets the approve sample command. /// public RelayCommand ApproveSampleCommand { get; set; } /// /// Gets or sets the repeat sample dye command. /// public RelayCommand RepeatSampleDyeCommand { get; set; } /// /// Gets or sets another sample command. /// public RelayCommand AnotherSampleCommand { get; set; } /// /// Gets or sets the invoke fine tuning palette command. /// public RelayCommand InvokeFineTuningPaletteCommand { get; set; } /// /// Gets or sets the reset fine tuning command. /// public RelayCommand ResetFineTuningCommand { get; set; } /// /// Gets or sets the start fine tuning command. /// public RelayCommand StartFineTuningCommand { get; set; } /// /// Gets or sets the approve fine tuning command. /// public RelayCommand ApproveFineTuningCommand { get; set; } /// /// Gets or sets the repeat fine tuning command. /// public RelayCommand RepeatFineTuningCommand { get; set; } #endregion #region Constructors /// /// Initializes the class. /// static JobViewVM() { _jobs_fine_tune_items = new Dictionary>(); } /// /// Initializes a new instance of the class. /// public JobViewVM() { RegisterForMessage(HandleJobSelectedMessage); FineTuneItems = new ObservableCollection(); ApprovalFineTuneItems = new ObservableCollection(); CustomersAutoCompleteProvider = new AutoCompleteProvider((customer, filter) => { return customer.Name.ToLower().StartsWith(filter != null ? filter.ToLower() : String.Empty); }); //Initialize Commands AddSolidSegmentCommand = new RelayCommand(() => AddSolidSegment()); AddBrushStopCommand = new RelayCommand(AddBrushStop); AddGradientSegmentCommand = new RelayCommand(() => AddGradientSegment()); SegmentDroppedCommand = new RelayCommand((e) => { DragAndDropSegment( (e.Draggable as FrameworkElement).DataContext as Segment, (e.Droppable as FrameworkElement).DataContext as Segment); }); RemoveSegmentCommand = new RelayCommand(RemoveSegment); RemoveBrushStopCommand = new RelayCommand(RemoveBrushStop); RemoveJobCommand = new RelayCommand(RemoveJob); SaveJobCommand = new RelayCommand(() => SaveJob()); ReplaceBrushStopCommand = new RelayCommand(InvokeColorAdjustmentForBrushStop); IncreaseDecreaseSamplesToDyeCommand = new RelayCommand((x) => { if (x == "+") { Job.SampleUnitsOrMeters++; } else { Job.SampleUnitsOrMeters--; } }); _check_gamut_thread = new Thread(CheckGamutThreadMethod); _check_gamut_thread.IsBackground = true; StartSampleDyeCommand = new RelayCommand(StartSampleDye); DyeCommand = new RelayCommand(StartJob, CanStartJob); ApproveSampleCommand = new RelayCommand(ApproveSampleDye); RepeatSampleDyeCommand = new RelayCommand(RepeatSampleDye); AnotherSampleCommand = new RelayCommand(DyeAnotherSample); InvokeFineTuningPaletteCommand = new RelayCommand(InvokeFineTuningPalette); ResetFineTuningCommand = new RelayCommand(ResetFineTuning); StartFineTuningCommand = new RelayCommand(StartFineTuning, () => FineTuneItems.Any(x => x.IsSelected)); RepeatFineTuningCommand = new RelayCommand(RepeatFineTuning); ApproveFineTuningCommand = new RelayCommand(ApproveFineTuning); } #endregion #region Job Management /// /// Loads the job. /// private async void LoadJob() { try { if (!(_job_to_load == null || (_job_to_load != null && Job != null && _job_to_load.Guid == Job.Guid))) { LogManager.Log($"Loading selected job '{_job_to_load.Name}'..."); NotificationProvider.SetGlobalBusyMessage("Loading job details..."); _can_navigate_back = false; _db = ObservablesContext.CreateDefault(); Job = await new JobBuilder(_db).Set(_job_to_load.Guid) .WithConfiguration() .WithRML() .WithUser() .WithSegments() .WithBrushStops() .BuildAsync(); Job.ValidateOnPropertyChanged = true; LogManager.Log("Loading RMLS..."); Rmls = (await new RmlsCollectionBuilder(_db).Set().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().BuildAsync()).ToList(); LogManager.Log("Loading Color Spaces..."); ColorSpaces = await _db.ColorSpaces.ToListAsync(); LogManager.Log("Loading Spool Types..."); SpoolTypes = await _db.SpoolTypes.ToListAsync(); LogManager.Log("Loading Customers..."); Customers = await _db.Customers.Where(x => x.OrganizationGuid == MachineProvider.Machine.OrganizationGuid).ToListAsync(); if (!_check_gamut_thread.IsAlive) { _check_gamut_thread.Start(); } SegmentsCollectionView = CollectionViewSource.GetDefaultView(Job.Segments); SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending)); InvokeUIOnIdle(() => { NotificationProvider.ReleaseGlobalBusyMessage(); }); _job_to_load = null; } if (!_jobs_fine_tune_items.ContainsKey(Job.Guid) && Job.JobFineTuningStatus == BL.Enumerations.FineTuningStatuses.PendingApproval) { Job.JobFineTuningStatus = BL.Enumerations.FineTuningStatuses.Unspecified; } LogManager.Log($"Job editing state = '{Job.JobEditingState}'."); if (Job.JobEditingState == BL.Enumerations.EditingStates.SampleDye && Job.JobSampleDyeStatus == BL.Enumerations.SampleDyeStatuses.PendingApproval) { LogManager.Log("Directing view to display sample dye region."); View.DisplaySampleDye(); } else if (Job.JobEditingState == BL.Enumerations.EditingStates.FineTuning && Job.JobFineTuningStatus == BL.Enumerations.FineTuningStatuses.PendingApproval) { LogManager.Log("Directing view to display fine tuning region."); View.DisplayFineTuning(); } } catch (Exception ex) { LogManager.Log(ex, $"Error loading job '{_job_to_load.Name}'"); await NotificationProvider.ShowError("An error occurred while trying to load the selected job."); } } /// /// Saves the job. /// private async void SaveJob(bool displayNotification = true) { try { if (Job.Validate(_db)) { LogManager.Log("Saving job..."); await _db.SaveChangesAsync(); RaiseMessage(new JobSavedMessage() { Job = Job }); if (displayNotification) { await NotificationProvider.ShowInfo(String.Format("Job '{0}' saved successfully.", Job.Name)); } } } catch (Exception ex) { LogManager.Log(ex, $"Error saving job '{Job.Name}'."); await NotificationProvider.ShowError("An error occurred while trying to save the job."); } } /// /// Removes the job. /// private async void RemoveJob() { try { LogManager.Log("Removing job..."); if (await NotificationProvider.ShowQuestion("Are you sure you want to delete the this job?")) { await Job.DeleteCascadeAsync(_db); RaiseMessage(new JobRemovedMessage() { Job = Job }); _can_navigate_back = true; await NavigationManager.NavigateBack(); } } catch (Exception ex) { LogManager.Log(ex, $"Error removing job '{Job.Name}'."); await NotificationProvider.ShowError("An error occurred while trying to remove the job."); } } /// /// Starts the job. /// private void StartJob() { try { LogManager.Log("Start job command pressed. Starting job and navigating to job progress view..."); PrintingManager.Print(Job, _db); NavigationManager.NavigateTo(nameof(JobProgressView)); } catch (Exception ex) { LogManager.Log(ex, "Could not start the current job."); NotificationProvider.ShowError($"Cannot start job.\n{ex.Message}."); } } /// /// Determines whether this instance [can start job]. /// private bool CanStartJob() { return Job != null && !Job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.IsOutOfGamut); } #endregion #region Segments Management /// /// Adds a new solid segment. /// private Segment AddSolidSegment() { try { LogManager.Log("Adding new solid segment..."); return Job.AddSolidSegment(MachineProvider.Machine.DefaultSegmentLength > 0 ? MachineProvider.Machine.DefaultSegmentLength : 10); } catch (Exception ex) { LogManager.Log(ex, "Could not add a new solid segment."); NotificationProvider.ShowError("An error occurred while trying to add a new segment."); return null; } } /// /// Adds a new gradient segment. /// private Segment AddGradientSegment() { try { LogManager.Log("Adding new gradient segment..."); return Job.AddGradientSegment(MachineProvider.Machine.DefaultSegmentLength > 0 ? MachineProvider.Machine.DefaultSegmentLength : 10); } catch (Exception ex) { LogManager.Log(ex, "Could not add a new gradient segment."); NotificationProvider.ShowError("An error occurred while trying to add a new segment."); return null; } } /// /// Called when a segment has been dragged and dropped into another segment. /// /// The dragged job. /// The dropped job. private void DragAndDropSegment(Segment draggedSegment, Segment droppedSegment) { LogManager.Log($"Segment Drag & Drop '{draggedSegment.SegmentIndex}' => '{droppedSegment.SegmentIndex}'."); if (draggedSegment.SegmentIndex > droppedSegment.SegmentIndex) { draggedSegment.SegmentIndex = droppedSegment.SegmentIndex - 1; } else { draggedSegment.SegmentIndex = droppedSegment.SegmentIndex + 1; } int index = 1; foreach (var segment in Job.Segments.OrderBy(x => x.SegmentIndex)) { segment.SegmentIndex = index++; } SegmentsCollectionView.Refresh(); } /// /// Removes the segment. /// /// The segment. private async void RemoveSegment(Segment segment) { try { if (await NotificationProvider.ShowQuestion("Are you sure you want to remove the selected segment?")) { LogManager.Log($"Removing job segment {segment.SegmentIndex}"); segment.BrushStops.ToList().ForEach(x => { _db.BrushStops.Remove(x); }); _db.Segments.Remove(segment); } } catch (Exception ex) { LogManager.Log(ex, "Could not remove segment."); await NotificationProvider.ShowError("An error occurred while trying to add a new segment."); } } #endregion #region Brush Stops Management /// /// Adds a new brush stop to the specified segment. /// /// The segment. private void AddBrushStop(Segment segment) { LogManager.Log($"Adding new brush stop to segment {segment.SegmentIndex}."); segment.AddBrushStop(); } /// /// Removes the brush stop. /// /// The brush stop. private void RemoveBrushStop(BrushStop brushStop) { if (brushStop.Segment.BrushStops.Count > 2) { LogManager.Log($"removing brush stop {brushStop.StopIndex} from segment {brushStop.Segment.SegmentIndex}."); _db.BrushStops.Remove(brushStop); } else { NotificationProvider.ShowInfo("Gradient segments must contain at least two colors."); } } /// /// Invokes the color adjustment for the specified brush stop. /// /// The brush stop. private async void InvokeColorAdjustmentForBrushStop(BrushStop brushStop) { try { LogManager.Log($"Invoking triplet color adjustment dialog for brush stop {brushStop.StopIndex} at segment {brushStop.Segment.SegmentIndex}."); LogManager.Log("Retrieving color conversion suggestions for brush stop..."); var conversionOutput = TangoColorConverter.GetSuggestions(brushStop); BasicColorCorrectionViewVM vm = null; vm = await NotificationProvider.ShowDialog(new BasicColorCorrectionViewVM() { InvalidBrushStop = brushStop, Suggestions = TangoColorConverter.CreateTrippletSuggestions(conversionOutput), }); if (vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.MoreOptions) { LogManager.Log("Invoking hive color conversion dialog..."); vm = await NotificationProvider.ShowDialog(new AdvancedColorCorrectionViewVM() { InvalidBrushStop = brushStop, Suggestions = TangoColorConverter.CreateHiveSuggestions(conversionOutput), }); } if (vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.Confirmed) { LogManager.Log($"Color suggestion selected: {vm.SelectedSuggestion.Color.ToString()}."); brushStop.Color = vm.SelectedSuggestion.Color; brushStop.Corrected = true; brushStop.IsOutOfGamut = false; brushStop.OutOfGamutChecked = true; } } catch (Exception ex) { LogManager.Log(ex, "Error while invoking color adjustment dialog."); await NotificationProvider.ShowError("An error occurred while trying to convert the selected color."); } } /// /// Called when the brush stop field value has been changed (This called from the view!). /// /// The brush stop. public void OnBrushStopFieldValueChanged(BrushStop brushStop) { brushStop.Corrected = false; brushStop.OutOfGamutChecked = false; } #endregion #region Job Selection Message /// /// Handles the job selected message. /// /// The message. private void HandleJobSelectedMessage(JobSelectedMessage message) { _job_to_load = message.Job; } #endregion #region Sample Dye /// /// Starts a sample dye. /// private void StartSampleDye() { try { LogManager.Log("Sample dye command pressed..."); PrintingManager.PrintSample(Job, _db); NavigationManager.NavigateTo(nameof(JobProgressView)); } catch (Exception ex) { LogManager.Log(ex, $"Error executing sample dye for job {Job.Name}."); NotificationProvider.ShowError("An error occurred while trying to execute the sample dye."); } } /// /// Sets the job status back to not approved. /// private void RepeatSampleDye() { LogManager.Log("Repeat sample dye command pressed..."); Job.JobEditingState = BL.Enumerations.EditingStates.Default; Job.JobSampleDyeStatus = BL.Enumerations.SampleDyeStatuses.Unspecified; } /// /// Approves the sample dye. /// private void ApproveSampleDye() { LogManager.Log("Approve sample dye command pressed..."); Job.JobEditingState = BL.Enumerations.EditingStates.Default; Job.JobSampleDyeStatus = BL.Enumerations.SampleDyeStatuses.Approved; Job.SampleDyeApproveDate = DateTime.UtcNow; SaveJob(false); } /// /// Dyes another sample. /// private void DyeAnotherSample() { LogManager.Log("Dye another sample dye command pressed..."); Job.JobEditingState = BL.Enumerations.EditingStates.Default; Job.JobSampleDyeStatus = BL.Enumerations.SampleDyeStatuses.Unspecified; } #endregion #region Fine Tuning /// /// Synchronizes the fine tune items to brush stops. /// private void SyncFineTuneItemsToBrushStops() { try { if (Job != null) { if (_jobs_fine_tune_items.ContainsKey(Job.Guid)) { FineTuneItems = _jobs_fine_tune_items[Job.Guid].ToObservableCollection(); } else { FineTuneItems.Clear(); foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).DistinctBy(x => x.Color)) { FineTuneItem item = new FineTuneItem(TangoColorConverter.GetSuggestions(stop)); item.BrushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.Color == stop.Color).ToList(); item.SelectedSuggestion = item.Suggestions[item.Suggestions.Count / 2]; item.SelectedChanged += () => StartFineTuningCommand.RaiseCanExecuteChanged(); FineTuneItems.Add(item); } _jobs_fine_tune_items[Job.Guid] = FineTuneItems.ToList(); } ApprovalFineTuneItems = FineTuneItems.Where(x => x.IsSelected).ToObservableCollection(); StartFineTuningCommand.RaiseCanExecuteChanged(); } } catch (Exception ex) { LogManager.Log(ex, "Error while trying to synchronize fine tuning itmes with brush stops."); } } /// /// Invokes the fine tuning palette dialog. /// /// The fine tune item. private async void InvokeFineTuningPalette(FineTuneItem fineTuneItem) { LogManager.Log("Invoke fine tuning palette command pressed..."); try { FineTuningPaletteViewVM vm = new FineTuningPaletteViewVM(fineTuneItem, Job); await NotificationProvider.ShowDialog(vm); if (vm.DialogResult) { fineTuneItem.Suggestions = vm.Suggestions; fineTuneItem.SelectedSuggestion = vm.SelectedSuggestion; } } catch (Exception ex) { LogManager.Log(ex, "Error invoking the fine tunning palette"); await NotificationProvider.ShowError("An error occurred while trying to display the fine tunning palette."); } } /// /// Resets the fine tuning. /// private void ResetFineTuning() { SyncFineTuneItemsToBrushStops(); } /// /// Starts the fine tuning. /// private void StartFineTuning() { try { LogManager.Log("Start fine tunning job command pressed..."); _jobs_fine_tune_items[Job.Guid] = FineTuneItems.ToList(); PrintingManager.PrintFineTuning(Job, _db, FineTuneItems); NavigationManager.NavigateTo(nameof(JobProgressView)); } catch (Exception ex) { LogManager.Log(ex, "Error executing fine tuning job."); NotificationProvider.ShowError("An error occurred while trying to start the fine tuning job."); } } /// /// Approves the fine tuning. /// private void ApproveFineTuning() { LogManager.Log("Approve fine tuning command pressed."); Job.JobEditingState = BL.Enumerations.EditingStates.Default; Job.JobFineTuningStatus = BL.Enumerations.FineTuningStatuses.Approved; foreach (var item in ApprovalFineTuneItems) { foreach (var stop in item.BrushStops) { stop.Color = item.SelectedSuggestion.Color; } } Job.FineTuningApproveDate = DateTime.UtcNow; SaveJob(false); if (_jobs_fine_tune_items.ContainsKey(Job.Guid)) { _jobs_fine_tune_items.Remove(Job.Guid); } SyncFineTuneItemsToBrushStops(); } /// /// Repeats the fine tuning. /// private void RepeatFineTuning() { LogManager.Log("Repeat fine tuning command pressed."); Job.JobEditingState = BL.Enumerations.EditingStates.Default; Job.JobFineTuningStatus = BL.Enumerations.FineTuningStatuses.Unspecified; } #endregion #region Out Of Gamut Check Thread /// /// Iterates over all brush stops and checks for out of gamut. /// private void CheckGamutThreadMethod() { while (true) { Thread.Sleep(500); if (Job != null && IsVisible && (Job.ColorSpace != null && Job.ColorSpace.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32())) { var brushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.Corrected && !x.OutOfGamutChecked).ToList(); foreach (var stop in brushStops) { try { stop.IsOutOfGamut = TangoColorConverter.IsOutOfGamut(stop); stop.OutOfGamutChecked = true; } catch { LogManager.Log($"Out of gamut check failed for brush stop {stop.StopIndex} at segment {stop.Segment.SegmentIndex}.", LogCategory.Warning); } } if (brushStops.Count > 0) { InvokeUI(() => { DyeCommand.RaiseCanExecuteChanged(); }); } } } } #endregion #region IPPC ViewModel Overrides /// /// Called when the application has been started. /// public override void OnApplicationStarted() { base.OnApplicationStarted(); } /// /// Called when the navigation system has navigated to this VM view. /// public override void OnNavigatedTo() { base.OnNavigatedTo(); LoadJob(); } /// /// Called when the navigation system has navigated from this VM view. /// public override void OnNavigatedFrom() { base.OnNavigatedFrom(); _job_to_load_intent = JobNavigationIntent.Default; } /// /// Called before the navigation system navigates back from this object. /// Return false to abort the navigation. /// /// public async override Task OnNavigateBackRequest() { bool result = true; if (!_can_navigate_back) { if (await NotificationProvider.ShowQuestion("Are you sure you want to exit this job?")) { Job = null; SegmentsCollectionView = null; } else { result = false; } } return result; } #endregion #region INavigationObjectReceiver public void OnNavigatedToWithObject(JobNavigationObject e) { _job_to_load_intent = e.Intent; _job_to_load = e.Job; } #endregion } }