Files
BeWoPlaner/BeWo/Scheduler/ViewModel/SchedulerAppointmentListVM.cs
Lyndon Jetten 1fd6040f58 Kilometerauswertung für Mitarbeiter
Ressourcencheck ist jetzt korrekt
Weiterentwicklung der Quittierungsbelege für die Mobilversion
2020-09-30 19:23:42 +02:00

679 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Xml;
using BeWo.Scheduler.Utils;
using BeWo.Scheduler.View;
using BeWo.ServiceProxy;
using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using DevExpress.Xpf.Scheduler;
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.Native;
using SchedulerControl = DevExpress.Xpf.Scheduler.SchedulerControl;
using SchedulerStorage = DevExpress.Xpf.Scheduler.SchedulerStorage;
namespace BeWo.Scheduler.ViewModel
{
public class SchedulerAppointmentListVM : AbstractDCListMapperVM<SchedulerAppointmentDC, SchedulerAppointmentVM>, ISchedulerViewModel
{
public bool ShouldLockOverlappingAppointmentCheck { get; set; }
public SchedulerSettings GetDefaultSchedulerSettings()
{
var settings = new SchedulerSettings(AppointmentKind.General, AppointmentViewType.WorkWeek);
return settings;
}
private BindingList<IBeWoAppointment> _AppointmentList;
public BindingList<IBeWoAppointment> Appointments
{
get
{
if (_AppointmentList != null)
{
return _AppointmentList;
}
_AppointmentList = new BindingList<IBeWoAppointment>();
_AppointmentList.AddingNew += AppointmentListAddingNew;
foreach (var item in VMList)
{
_AppointmentList.Add(item);
}
return _AppointmentList;
}
}
private readonly List<CompactCustomerDC> _AllCustomers;
private readonly List<CompactEmployeeDC> _AllEmployees;
private readonly Dictionary<ValueListEntryDC, List<ResourceDC>> _Categories2Resources;
private static void AppointmentListAddingNew(object sender, AddingNewEventArgs e)
{
var dc = new SchedulerAppointmentDC
{
EmployeeList = new List<Employee2SchedulerAppointmentDC>(),
CustomerList = new List<CompactCustomerDC>(),
ResourceList = new List<ResourceDC>(),
Status = 0
};
var neu = new SchedulerAppointmentVM(dc);
e.NewObject = neu;
}
private Dictionary<Guid, Dictionary<string, Dictionary<string, object>>> _ChangedOccurenceCustomFields;
public Dictionary<Guid, Dictionary<string, Dictionary<string, object>>> ChangedOccurenceCustomFields { get; }
public List<CompactCustomerDC> AllCustomers => _AllCustomers;
public List<CompactEmployeeDC> AllEmployees => _AllEmployees;
public Dictionary<ValueListEntryDC, List<ResourceDC>> Categories2Resources => _Categories2Resources;
private Appointment _GeoeffneterTermin;
public SchedulerAppointmentListVM(List<SchedulerAppointmentDC> appList, List<CompactCustomerDC> allCustomers, List<CompactEmployeeDC> allEmployees, Dictionary<ValueListEntryDC, List<ResourceDC>> lCategoriesToResources) : base(appList)
{
_Categories2Resources = lCategoriesToResources;
_AllCustomers = allCustomers;
_AllEmployees = allEmployees;
// TODO: Hier Rechte beachten!
InitChangedOccurrencyCustomFields(appList.Where(t => t.Type == 3).ToList());
InitViewModel();
}
private void InitViewModel()
{
foreach (var item in VMList)
{
item.CustomFields.Add(nameof(CustomFieldStorage), new CustomFieldStorage(item));
item.Id = item.DataContract.SchedulerAppointmentOid;
if (!item.IsPrivate || item.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) || item.EmployeeList.Select(s => s.Employee).Contains(BeWoApp.CompactLoggedOnEmployee))
{
continue;
}
item.Description = "Privater Termin";
item.Subject = $"Privat ({item.Originator})";
}
}
public void UpdateViewModel(IEnumerable<SchedulerAppointmentDC> updatedDcList)
{
foreach (var dc in updatedDcList)
{
SchedulerAppointmentVM found = null;
foreach (var vm in Appointments.OfType<SchedulerAppointmentVM>().Where(vm => vm.DataContract != null && vm.DataContract.Equals(dc)))
{
found = vm;
}
if (found != null)
{
found.DataContract = dc;
}
}
}
public void SaveAppointments(SchedulerControl control, IEnumerable<Appointment> list)
{
var areEqual = false;
var dcList = new List<SchedulerAppointmentDC>();
foreach (var item in list)
{
if (!(item.GetSourceObject(control.GetCoreStorage()) is SchedulerAppointmentVM vm))
{
continue;
}
UpdateSchedulerAppointment(item, vm);
if(vm.ResourceList.Any())
{
if(!CheckForUnavailableResources(vm))
{
return;
}
}
if (!ShouldLockOverlappingAppointmentCheck && vm.EventType != 3 && !vm.IsTask)
{
var isOverlapping = false;
ServiceFacade.DoResourceServiceSync(s => isOverlapping = s.OverlappingAppointmentsExist(
vm.Start,
vm.End,
vm.EmployeeList.Select(emp => emp.Employee.EmployeeOid).ToList(),
vm.CustomerList.Select(cc => cc.CustomerOid).ToList(),
vm.ResourceList.Select(r => r.ResourceOid.Value).ToList(),
vm.Originator.EmployeeOid,
vm.DataContract.SchedulerAppointmentOid,
item.RecurrenceInfo?.Id.ToString() ?? string.Empty, item.RecurrenceIndex));
if (isOverlapping)
{
var erg = MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen bereits existierenden Termin.\nMöchten Sie ihn wirklich speichern?", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (erg.Equals(MessageBoxResult.No))
{
return;
}
}
}
if (item.Type.Equals(AppointmentType.ChangedOccurrence) && _GeoeffneterTermin != null)
{
areEqual = _GeoeffneterTermin.Equals(item);
}
if(!areEqual)
{
dcList.Add(vm.CommitToDataContract());
}
}
if (dcList.Count <= 0)
{
return;
}
NewSchedulerView.IgnoreChangeEvents = true;
var mostRecentAppointments = new List<SchedulerAppointmentDC>();
ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.UpdateSchedulerAppointments(dcList));
UpdateViewModel(mostRecentAppointments);
control.ActiveView.LayoutChanged();
NewSchedulerView.IgnoreChangeEvents = false;
}
public void InsertAppointments(SchedulerControl control, IEnumerable<Appointment> list)
{
var dcList = new List<SchedulerAppointmentDC>();
foreach (var item in list)
{
if (!(item.GetSourceObject(control.GetCoreStorage()) is SchedulerAppointmentVM vm))
{
if(item.IsException && item.CF_HasServiceRecordEntry())
{
var dc = new SchedulerAppointmentDC
{
IsPrivate = item.CF_IsPrivate(),
Subject = item.Subject,
Description = item.Description,
StartDate = item.Start,
EndDate = item.End,
Originator = item.CF_Originator(),
LabelId = item.LabelId,
AllDay = item.AllDay,
Status = item.StatusId,
Type = (int) item.Type,
Location = item.Location,
RecurrenceInfo = item.RecurrenceInfo.ToXml(),
ReminderInfo = item.Reminder?.ToXml(),
CustomerList = item.CF_CustomerList(),
EmployeeList = item.CF_EmployeeList().ToList(),
ResourceList = item.CF_ResourceList(),
SupportConceptList = item.CF_SupportConceptList(),
RecurrenceIndex = item.RecurrenceIndex,
RecurrenceId = item.RecurrenceInfo.Id.ToString(),
HasServiceRecordEntry = item.CF_HasServiceRecordEntry()
};
vm = new SchedulerAppointmentVM(dc);
}
else
{
continue;
}
}
UpdateSchedulerAppointment(item, vm);
if(vm.ResourceList.Any())
{
if(!CheckForUnavailableResources(vm))
{
return;
}
}
if (!ShouldLockOverlappingAppointmentCheck && !vm.IsTask)
{
var isOverlapping = false;
ServiceFacade.DoResourceServiceSync(s => isOverlapping = s.OverlappingAppointmentsExist(
vm.Start,
vm.End,
vm.EmployeeList.Select(emp => emp.Employee.EmployeeOid).ToList(),
vm.CustomerList.Select(cc => cc.CustomerOid).ToList(),
vm.ResourceList.Select(r => r.ResourceOid.Value).ToList(),
vm.Originator.EmployeeOid,
vm.DataContract.SchedulerAppointmentOid,
item.RecurrenceInfo?.Id.ToString() ?? string.Empty, item.RecurrenceIndex));
if (isOverlapping)
{
var erg = MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen bereits existierenden Termin.\nMöchten Sie ihn wirklich speichern?", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (erg.Equals(MessageBoxResult.No))
{
return;
}
}
}
dcList.Add(vm.CommitToDataContract());
}
if (dcList.Count <= 0)
{
return;
}
NewSchedulerView.IgnoreChangeEvents = true;
var mostRecentAppointments = new List<SchedulerAppointmentDC>();
ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.InsertSchedulerAppointments(dcList));
UpdateViewModel(mostRecentAppointments);
control.ActiveView.LayoutChanged();
NewSchedulerView.IgnoreChangeEvents = false;
}
private void UpdateSchedulerAppointment(Appointment app, SchedulerAppointmentVM vm)
{
vm.EmployeeList = app.CF_EmployeeList();
vm.CustomerList = app.CF_CustomerList();
vm.ResourceList = app.CF_ResourceList();
vm.Originator = app.CF_Originator();
vm.IsPrivate = app.CF_IsPrivate();
vm.IsTask = app.CF_IsTask();
vm.DueDate = app.CF_DueDate();
vm.CompletedDate = app.CF_CompletedDate();
vm.CompletedNotice = app.CF_CompletedNotice();
vm.TaskDescription = app.CF_TaskDescription();
vm.SupportConceptList = app.CF_SupportConceptList();
vm.HasServiceRecordEntry = app.CF_HasServiceRecordEntry();
if(vm.IsTask)
{
vm.AllDay = true;
if(vm.DueDate.HasValue)
{
vm.DueDate = vm.Start.MergeDatesByDate(vm.DueDate.Value);
vm.DueTime = vm.DueDate;
}
}
if(!vm.CustomFields.ContainsKey(nameof(CustomFieldStorage)))
{
vm.CustomFields.Add(nameof(CustomFieldStorage), new CustomFieldStorage(vm));
}
if (vm.CommitToDataContract() != null && vm.CommitToDataContract().SchedulerAppointmentOid.HasValue && vm.EmployeeList != null && vm.EmployeeList.Count > 0)
{
var alt = new SchedulerAppointmentDC();
ServiceFacade.DoResourceServiceSync(s => alt = s.GetSchedulerAppointmentsById(new List<long> {vm.CommitToDataContract().SchedulerAppointmentOid.Value}).First());
var alts = alt.StartDate;
var alte = alt.EndDate;
if(alts != vm.Start || alte != vm.End)
{
var neu = vm.EmployeeList;
vm.EmployeeList = new ObservableCollection<Employee2SchedulerAppointmentDC>(neu.DoForEach(f =>
{
if(!f.Employee.Equals(vm.Originator))
{
f.ParticipationAnswer = ParticipationAnswer.Offen;
}
}).ToList());
}
}
if (vm.ResourceList == null || vm.ResourceList.Count <= 0) return;
if (app.RecurrenceInfo != null)
{
var index = app.RecurrenceIndex.ToString();
var id = new Guid(app.RecurrenceInfo.Id.ToString());
if (_ChangedOccurenceCustomFields.ContainsKey(id) && _ChangedOccurenceCustomFields[id].ContainsKey(index))
{
if (app.Type.Equals(AppointmentType.ChangedOccurrence))
{
app.CustomFields[nameof(CustomFieldStorage)] = _ChangedOccurenceCustomFields[id][index][nameof(CustomFieldStorage)];
}
}
}
app.LabelId = vm.LabelId;
}
AbstractAppointmentEditForm ISchedulerViewModel.GetEditAppointmentForm(SchedulerControl control, Appointment appointment)
{
_GeoeffneterTermin = control.Storage.CreateAppointment(AppointmentType.Normal);
_GeoeffneterTermin.AllDay = appointment.AllDay;
_GeoeffneterTermin.Start = appointment.Start;
_GeoeffneterTermin.End = appointment.End;
_GeoeffneterTermin.Description = appointment.Description;
foreach (CustomField cf in appointment.CustomFields)
{
_GeoeffneterTermin.CustomFields[cf.Name] = cf.Value;
}
var isTask = _GeoeffneterTermin.CF_IsTask();
if (!appointment.Type.Equals(AppointmentType.ChangedOccurrence))
{
return new SchedulerAppointmentEditForm(this, control, appointment, _AllEmployees, _AllCustomers, _Categories2Resources, isTask);
}
var index = appointment.RecurrenceIndex;
var id = new Guid(appointment.RecurrenceInfo.Id.ToString());
if (_ChangedOccurenceCustomFields.ContainsKey(id) && _ChangedOccurenceCustomFields[id].ContainsKey(index.ToString()))
{
var specialCustomFields = _ChangedOccurenceCustomFields[id][index.ToString()];
foreach (var cf in specialCustomFields)
{
appointment.CustomFields[cf.Key] = cf.Value;
_GeoeffneterTermin.CustomFields[cf.Key] = cf.Value;
}
}
return new SchedulerAppointmentEditForm(this, control, appointment, _AllEmployees, _AllCustomers, _Categories2Resources, isTask);
}
public void ApplyChangesToChangedOccurencyCustomFields(ObservableCollection<Employee2SchedulerAppointmentDC> employees, List<CompactCustomerDC> customers, List<ResourceDC> resources, CompactEmployeeDC originator, bool isPrivate, string index, Guid id, bool isTask, string taskDescription, DateTime? completedDate, DateTime? dueDate, string completedNotice, List<CompactSupportConceptDC> supportConcepts, string subject, bool isAllDay)
{
if (!_ChangedOccurenceCustomFields.ContainsKey(id) || !_ChangedOccurenceCustomFields[id].ContainsKey(index))
{
return;
}
_ChangedOccurenceCustomFields[id][index][nameof(CustomFieldStorage)] = new CustomFieldStorage(employees, customers, resources, originator, isPrivate, isTask, taskDescription, dueDate, completedDate, completedNotice, supportConcepts, subject, isAllDay);
}
public void AddCustomFieldsMapping(SchedulerStorage schedulerStorage)
{
var customFieldStorageMapping = new SchedulerCustomFieldMapping(nameof(CustomFieldStorage), nameof(CustomFieldStorage));
schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(customFieldStorageMapping);
}
public void InitNewAppointment(Appointment appointment)
{
appointment.StatusId = 0;
appointment.CustomFields[nameof(CustomFieldStorage)] = new CustomFieldStorage { Originator = BeWoApp.CompactLoggedOnEmployee };
}
public void InitNewTask(Appointment pAppointment, DateTime? pDueDate, IEnumerable<Employee2SchedulerAppointmentDC> pSelectedEmployees, List<CompactCustomerDC> pSelectedCustomers, List<ResourceDC> pSelectedResources, List<CompactSupportConceptDC> pSelectedSupportConcepts)
{
pAppointment.CustomFields[nameof(CustomFieldStorage)] = new CustomFieldStorage
{
Originator = BeWoApp.CompactLoggedOnEmployee,
EmployeeList = new ObservableCollection<Employee2SchedulerAppointmentDC>(pSelectedEmployees ?? new List<Employee2SchedulerAppointmentDC>()),
CustomerList = pSelectedCustomers ?? new List<CompactCustomerDC>(),
ResourceList = pSelectedResources ?? new List<ResourceDC>(),
SupportConceptList = pSelectedSupportConcepts ?? new List<CompactSupportConceptDC>(),
TaskDescription = string.Empty,
DueDate = pDueDate,
IsTask = true
};
pAppointment.StatusId = 0;
}
public bool HideAppointment(string filterCategory, object selectedObject, Appointment appointment, bool showPrivateAppointments, bool showAbsenceTimes, bool pShowTasks)
{
if (appointment.GetCustomFieldStorage() == null)
{
return false;
}
var wirdAngezeigt = true; // -> wird standardmäßig angezeigt
var isPrivate = appointment.CF_IsPrivate();
var isAbsenceTime = appointment.CF_IsAbsenceTime();
var isTask = appointment.CF_IsTask();
// Ist Abwesenheit, es sollen keine privaten Termine angezeigt werden und es sollen keine Abwesenheiten angezeigt werden
if(isAbsenceTime && !showPrivateAppointments && !showAbsenceTimes)
{
return !showAbsenceTimes;
}
if(showPrivateAppointments && !isPrivate)
{
return true;
}
if (!pShowTasks && isTask)
{
return true;
}
var ersteller = appointment.CF_Originator();
var employeeList = appointment.CF_EmployeeList();
var customerList = appointment.CF_CustomerList();
var resourceList = appointment.CF_ResourceList();
if (isPrivate)
{
if (ersteller == null || !ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid))
{
return true;
}
}
switch (filterCategory)
{
case "NurEigene":
var istEigenerTermin = ersteller != null && ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) && employeeList != null && employeeList.Count == 0 ||
employeeList != null && employeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid));
wirdAngezeigt = istEigenerTermin;
break;
case "NachAuswahl":
var dictionary = (Dictionary<string, object>) selectedObject;
var ressourcen = (List<ResourceDC>) dictionary["Ressourcen"];
var mitarbeiter = (List<CompactEmployeeDC>) dictionary["Mitarbeiter"];
var klienten = (List<CompactCustomerDC>) dictionary["Klienten"];
var cfe = employeeList?.Select(s => s.Employee).ToList();
var cfr = resourceList ?? new List<ResourceDC>();
var cfc = customerList ?? new List<CompactCustomerDC>();
var hasOnlyOriginatorInCommon = employeeList != null && ersteller != null && employeeList.Any() == false && mitarbeiter.Contains(ersteller);
var m = cfe.Intersect(mitarbeiter).ToList();
var r = cfr.Intersect(ressourcen).ToList();
var k = cfc.Intersect(klienten).ToList();
wirdAngezeigt = (m.Any() || k.Any() || r.Any()) || hasOnlyOriginatorInCommon;
break;
case "Ebenen":
var liste = (List<bool>) selectedObject; // mkr
var appEList = employeeList.Where(w => !w.Employee.Equals(appointment.CF_Originator())).ToList();
// Ersteller und Rechte beachten
var istEigen = ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid);
var mVorhanden = appEList.Any(a2app => _AllEmployees.Contains(a2app.Employee));
var kVorhanden = customerList.Any(_AllCustomers.Contains);
wirdAngezeigt = liste[0] && mVorhanden || liste[1] && resourceList.Any() || liste[2] && kVorhanden;
// Nur Ansehen
if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen) && liste[0] && mVorhanden && !appEList.Select(e2sa => e2sa.Employee).Any(a => a.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)))
{
wirdAngezeigt = false;
}
if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderKliententermineAlleAnsehen) && liste[2] && kVorhanden)
{
wirdAngezeigt = false;
}
if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderRessourcentermineAnsehen) && liste[1] && resourceList.Any())
{
wirdAngezeigt = false;
}
break;
}
// return false -> Termin wird angezeigt!
return !wirdAngezeigt;
}
public void InitChangedOccurrencyCustomFields(IEnumerable<SchedulerAppointmentDC> appList)
{
_ChangedOccurenceCustomFields = new Dictionary<Guid, Dictionary<string, Dictionary<string, object>>>();
foreach (var termin in appList)
{
var ri = new RecurrenceInfo();
ri.FromXml(termin.RecurrenceInfo);
string index;
using (var reader = XmlReader.Create(new StringReader(termin.RecurrenceInfo)))
{
reader.ReadToFollowing("RecurrenceInfo");
reader.MoveToAttribute("Index");
index = reader.Value;
}
if (index.Equals(""))
{
index = "0";
}
var customFieldCollection =
new Dictionary<string, object>
{
[nameof(CustomFieldStorage)] = new CustomFieldStorage(termin)
};
var id = new Guid(ri.Id.ToString());
if(!_ChangedOccurenceCustomFields.ContainsKey(id))
{
_ChangedOccurenceCustomFields.Add(id, new Dictionary<string, Dictionary<string, object>> { { index, customFieldCollection } });
}
else if(!_ChangedOccurenceCustomFields[id].ContainsKey(index))
{
_ChangedOccurenceCustomFields[id].Add(index, customFieldCollection);
}
else
{
_ChangedOccurenceCustomFields[id][index] = customFieldCollection;
}
}
}
//TODO: alle relevanten Eigenschaften beachten und eigene AreEqual Extension schreiben (erledigt) (https://www.devexpress.com/Support/Center/Question/Details/T270666)
public override bool Equals(object pObj)
{
var obj = (SchedulerAppointmentListVM) pObj;
if (obj == null)
{
return false;
}
var appointmentsAreEqual = Appointments == null && obj.Appointments == null || Appointments != null && Appointments.AreEqual(obj.Appointments);
var allCustomersAreEqual = AllCustomers == null && obj.AllCustomers == null ||
AllCustomers != null && obj.AllCustomers != null && AllCustomers.Count == obj.AllCustomers.Count &&
!AllCustomers
.Where(
(t, i) =>
!(
t.CustomerOid.Equals(obj.AllCustomers[i].CustomerOid) &&
t.CustomerVersion.Equals(obj.AllCustomers[i].CustomerVersion)
)
).Any();
var allEmployeesAreEqual = AllEmployees == null && obj.AllEmployees == null ||
AllEmployees != null && obj.AllEmployees != null && AllEmployees.Count == obj.AllEmployees.Count &&
!AllEmployees
.Where(
(t, i) =>
!(
t.EmployeeOid.Equals(obj.AllEmployees[i].EmployeeOid) &&
t.EmployeeVersion.Equals(obj.AllEmployees[i].EmployeeVersion)
)
).Any();
var areEqual =
VMList.AreEqual(obj.VMList) &&
IsDirty == obj.IsDirty &&
allCustomersAreEqual &&
allEmployeesAreEqual &&
appointmentsAreEqual &&
Equals(Categories2Resources, obj.Categories2Resources) &&
Equals(ChangedOccurenceCustomFields, obj.ChangedOccurenceCustomFields);
return areEqual;
}
private static bool CheckForUnavailableResources(SchedulerAppointmentVM vm)
{
var unavailableResources = new List<ResourceDC>();
ServiceFacade.DoResourceServiceSync(s => unavailableResources = s.CheckResourceAvailability(vm.Start, vm.End, vm.ResourceList.Select(resource => resource.ResourceOid.Value).ToList(), vm.DataContract?.SchedulerAppointmentOid));
if(unavailableResources.Any())
{
var names = string.Empty;
unavailableResources.DoForEach(resource => names += resource.Name + ", ");
names = names.TrimEnd(' ').TrimEnd(',');
var resourceCount = vm.ResourceList.Count;
var warningMessage = unavailableResources.Count > 1 ?
$"Ein{(resourceCount > 1 ? "ige" : "e")} der ausgewählten Ressourcen ({names}) sind" :
$"{(resourceCount > 1 ? "Eine der" : "Die")} ausgewählte{(resourceCount > 1 ? "n" : string.Empty)} Ressource{(resourceCount > 1 ? "n" : string.Empty)} ({names}) ist";
warningMessage += $" zum gewählten Zeitpunkt ({vm.Start.GetIntervalDescription(vm.End).TrimStart(' ')}) nicht verfügbar.\n\nMöchten Sie trotzdem speichern?";
var erg = MessageBox.Show(warningMessage, "Überschneidung", MessageBoxButton.YesNo);
if(erg.Equals(MessageBoxResult.No))
{
return false;
}
}
return true;
}
}
}