protected void afuUpload_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (e.State != AjaxControlToolkit.AjaxFileUploadState.Success) { return; } PendingFlight pf = new PendingFlight() { User = Page.User.Identity.Name }; string szOriginal = pf.FlightData = System.Text.Encoding.UTF8.GetString(e.GetContents()); using (FlightData fd = new FlightData()) { fd.AutoFill(pf, (AutoFillOptions)Session[SessionKeyOpt]); pf.FlightData = string.Empty; LogbookEntry leEmpty = new PendingFlight() { User = Page.User.Identity.Name, FlightData = string.Empty }; if (!pf.IsEqualTo(leEmpty)) { pf.TailNumDisplay = fd.TailNumber ?? string.Empty; pf.FlightData = szOriginal; pf.Commit(); } } }
public override LogbookEntry ToLogbookEntry() { PendingFlight pf = new PendingFlight() { Date = blockOut.Date, ModelDisplay = model, TailNumDisplay = tail, Route = String.Format(CultureInfo.InvariantCulture, Resources.LocalizedText.LocalizedJoinWithSpace, dep, arr), TotalFlightTime = Math.Max((decimal)blockIn.Subtract(blockOut).TotalHours, 0) }; if (position.CompareCurrentCultureIgnoreCase("CA") == 0) { pf.PIC = pf.TotalFlightTime; } if (position.CompareCurrentCultureIgnoreCase("FO") == 0) { pf.SIC = pf.TotalFlightTime; } pf.CustomProperties.SetItems(new CustomFlightProperty[] { CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropFlightNumber, flightNumber), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockOut, blockOut, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockIn, blockIn, true) }); return(pf); }
protected void EditPendingFlightInList(PendingFlight pendingFlight, List <PendingFlight> lst) { mvPendingFlights.SetActiveView(vwEdit); mfbEditFlight.SetPendingFlight(pendingFlight); int index = lst.IndexOf(pendingFlight); mfbEditFlight.SetNextFlight(index > 0 ? index - 1 : LogbookEntry.idFlightNone); mfbEditFlight.SetPrevFlight(index < lst.Count - 1 ? index : LogbookEntry.idFlightNone); // since save will ultimately remove this from the list. }
public override LogbookEntry ToLogbookEntry() { // Always return pending flights PendingFlight pf = new PendingFlight() { Date = FlightDate, Route = JoinStrings(new string[] { DepartureAirportCode.MostDescriptive, DestinationAirportCode.MostDescriptive }), FlightStart = TakeoffTime ?? DateTime.MinValue, FlightEnd = LandingTime ?? DateTime.MinValue, TailNumDisplay = AircraftRegistration ?? String.Empty, ModelDisplay = AircraftType ?? String.Empty, TotalFlightTime = totalFlightTime == null ? 0 : totalFlightTime.SafeParseDecimal(), Nighttime = NightFlightTime == null ? 0 : NightFlightTime.SafeParseDecimal(), PIC = PicTime == null ? 0 : PicTime.SafeParseDecimal(), SIC = SicTime == null ? 0 : SicTime.SafeParseDecimal(), Dual = DualPilotTimeReceived == null ? 0 : DualPilotTimeReceived.SafeParseDecimal(), CFI = DualPilotTimeGiven == null ? 0 : DualPilotTimeGiven.SafeParseDecimal(), FullStopLandings = DayLandingCount, NightLandings = NightLandingCount, Approaches = ApproachList.Length, User = Username }; Aircraft ac = BestGuessAircraftID(Username, pf.TailNumDisplay); List <CustomFlightProperty> lst = new List <CustomFlightProperty>() { CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropFlightNumber, FlightNumber), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropDutyStart, DutyStartTime ?? DateTime.MinValue, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropDutyEnd, DutyEndTime ?? DateTime.MinValue, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockOut, ActualDepartureTime ?? DateTime.MinValue, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockIn, ActualArrivalTime ?? DateTime.MinValue, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropNameOfPIC, Pic == null || String.IsNullOrEmpty(Pic.Surname) ? Commander : Pic.Surname), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropNameOfSIC, Sic == null || Sic.Surname == null ? string.Empty : Sic.Surname), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropMultiPilotTime, MultiPilotFlightTime == null ? 0 : MultiPilotFlightTime.SafeParseDecimal()), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropSolo, SoloFlightTime == null ? 0 : SoloFlightTime.DecimalFromHHMM()), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropNightTakeoff, NightTakeoffCount), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropIFRTime, IfrTime == null ? 0 : IfrTime.SafeParseDecimal()), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropApproachName, ApproachTypeList == null ? string.Empty : JoinStrings(ApproachTypeList)) }; if (ac != null) { pf.AircraftID = ac.AircraftID; if (ac.IsAnonymous) { lst.Add(CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropAircraftRegistration, pf.TailNumDisplay)); } } pf.CustomProperties.SetItems(lst); AutoComplete(pf); return(pf); }
protected void mfbEditFlight_FlightUpdated(object sender, LogbookEventArgs e) { Refresh(); mvPendingFlights.SetActiveView(vwList); if (e.IDNextFlight >= 0) { List <PendingFlight> lst = new List <PendingFlight>(Flights); PendingFlight pf = lst[e.IDNextFlight]; EditPendingFlightInList(pf, lst); } }
public void SetPendingFlight(PendingFlight pendingFlight) { if (pendingFlight == null) { throw new ArgumentNullException("pendingFlight"); } SetUpNewOrEdit(pendingFlight.FlightID); hdnPendingID.Value = pendingFlight.PendingID; InitFormFromLogbookEntry(pendingFlight); // Change next/previous wording to match the fact that pending flights, kinda by definition, can't be updated. lnkUpdateNext.Text = Resources.LocalizedText.EditFlightAddFlightNext; lnkUpdatePrev.Text = Resources.LocalizedText.EditFlightAddFlightPrev; }
protected void EditPendingFlightInList(PendingFlight pendingFlight, List <PendingFlight> lst) { if (lst == null) { throw new ArgumentNullException(nameof(lst)); } mvPendingFlights.SetActiveView(vwEdit); mfbEditFlight.SetPendingFlight(pendingFlight); int index = lst.IndexOf(pendingFlight); mfbEditFlight.SetNextFlight(index > 0 ? index - 1 : LogbookEntry.idFlightNone); mfbEditFlight.SetPrevFlight(index < lst.Count - 1 ? index : LogbookEntry.idFlightNone); // since save will ultimately remove this from the list. }
public override LogbookEntry ToLogbookEntry() { PendingFlight pf = new PendingFlight() { Date = DATE, Route = String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.LocalizedJoinWithSpace, DPS, ARS).Trim() }; pf.CustomProperties.SetItems(new CustomFlightProperty[] { CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropFlightNumber, FLTNO), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockOut, FixDateForTime(DATE, DEPL), true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockIn, FixDateForTime(DATE, ARRL), true) }); return(pf); }
protected void mfbEditFlight_FlightUpdated(object sender, LogbookEventArgs e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } Refresh(); mvPendingFlights.SetActiveView(vwList); if (e.IDNextFlight >= 0) { List <PendingFlight> lst = new List <PendingFlight>(Flights); PendingFlight pf = lst[e.IDNextFlight]; EditPendingFlightInList(pf, lst); } }
protected void btnAddPending_Click(object sender, EventArgs e) { if (String.IsNullOrWhiteSpace(hdnPendingID.Value)) { hdnPendingID.Value = new PendingFlight().PendingID; } PendingFlight le = (PendingFlight)InitLogbookEntryFromForm(); le.FlightData = mfbFlightInfo1.Telemetry; // No need - by definition - to handle errors. le.Commit(); FlightUpdated?.Invoke(sender, new LogbookEventArgs(le)); }
protected async void btnImportCloudAhoy_Click(object sender, EventArgs e) { Profile pf = MyFlightbook.Profile.GetUser(User.Identity.Name); CloudAhoyClient client = new CloudAhoyClient(!Branding.CurrentBrand.MatchesHost(Request.Url.Host)) { AuthState = pf.CloudAhoyToken }; DateTime?dtStart = null; if (mfbCloudAhoyStartDate.Date.HasValue()) { dtStart = mfbCloudAhoyStartDate.Date; } DateTime?dtEnd = null; if (mfbCloudAhoyEndDate.Date.HasValue()) { dtEnd = mfbCloudAhoyEndDate.Date; } try { IEnumerable <CloudAhoyFlight> rgcaf = await client.GetFlights(User.Identity.Name, dtStart, dtEnd); foreach (CloudAhoyFlight caf in rgcaf) { PendingFlight pendingflight = caf.ToLogbookEntry() as PendingFlight; if (pendingflight != null) { pendingflight.Commit(); } } // Avoid a "Thread was being aborted" (ThreadAbortException). Response.Redirect("~/Member/ReviewPendingFlights.aspx", false); Context.ApplicationInstance.CompleteRequest(); } catch (MyFlightbookException ex) { // Cloudahoy is sending back HTML lblCloudAhoyErr.Text = ex.Message; popupCloudAhoy.Show(); } catch (MyFlightbookValidationException ex) { lblCloudAhoyErr.Text = ex.Message; popupCloudAhoy.Show(); } }
public override LogbookEntry ToLogbookEntry() { PendingFlight pf = new PendingFlight() { Date = FlightDate, Route = this.Route }; pf.CustomProperties.SetItems(new CustomFlightProperty[] { CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockOut, BlockOut, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockIn, BlockIn, true), CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropFlightNumber, FlightNumber) }); return(pf); }
public override LogbookEntry ToLogbookEntry() { PendingFlight pf = new PendingFlight() { Date = FlightDate, Route = this.Route }; pf.CustomProperties = PropertiesWithoutNullOrDefault(new CustomFlightProperty[] { PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockOut, BlockOut, true), PropertyWithValue(CustomPropertyType.KnownProperties.IDBlockIn, BlockIn, true), PropertyWithValue(CustomPropertyType.KnownProperties.IDPropFlightNumber, FlightNumber) }).ToArray(); return(pf); }
protected void lnkAddPending_Click(object sender, EventArgs e) { if (String.IsNullOrWhiteSpace(hdnPendingID.Value)) { hdnPendingID.Value = new PendingFlight().PendingID; } PendingFlight le = (PendingFlight)InitLogbookEntryFromForm(); le.FlightData = mfbFlightInfo1.Telemetry; Aircraft ac = new Aircraft(le.AircraftID); le.TailNumDisplay = ac.DisplayTailnumber; le.ModelDisplay = ac.ModelDescription; // No need - by definition - to handle errors. le.Commit(); FlightUpdated?.Invoke(sender, new LogbookEventArgs(le)); }
public void SetPendingFlight(PendingFlight pendingFlight) { if (pendingFlight == null) { throw new ArgumentNullException(nameof(pendingFlight)); } SetUpNewOrEdit(pendingFlight.FlightID); hdnPendingID.Value = pendingFlight.PendingID; bool fShowUpdatePending = !String.IsNullOrWhiteSpace(pendingFlight.PendingID); if (fShowUpdatePending) { popmenuCommitAndNavigate.Visible = true; // so that setting the update pending below will stick } divUpdatePending.Visible = fShowUpdatePending; // allow update if this is an existing pending flight. popmenuPending.Visible = false; InitFormFromLogbookEntry(pendingFlight); // Change next/previous wording to match the fact that pending flights, kinda by definition, can't be updated. lnkUpdateNext.Text = Resources.LocalizedText.EditFlightAddFlightNext; lnkUpdatePrev.Text = Resources.LocalizedText.EditFlightAddFlightPrev; }
protected void gvPendingFlights_RowCommand(object sender, CommandEventArgs e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (String.Compare(e.CommandName, "Sort", StringComparison.OrdinalIgnoreCase) == 0) { return; } string idFlight = e.CommandArgument.ToString(); if (String.IsNullOrEmpty(idFlight)) { throw new MyFlightbookValidationException("Invalid ID!"); } List <PendingFlight> lst = new List <PendingFlight>(Flights); PendingFlight pendingFlight = lst.FirstOrDefault(pf => pf.PendingID.CompareCurrentCultureIgnoreCase(idFlight) == 0); if (pendingFlight == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "Pending flight with ID {0} not found.", idFlight)); } if (String.Compare(e.CommandName, "_Delete", StringComparison.OrdinalIgnoreCase) == 0) { pendingFlight.Delete(); lst.Remove(pendingFlight); gvPendingFlights.DataSource = Flights = lst; gvPendingFlights.DataBind(); } else if (String.Compare(e.CommandName, "_Edit", StringComparison.OrdinalIgnoreCase) == 0) { EditPendingFlightInList(pendingFlight, lst); } }
protected void Import(object sender, WizardNavigationEventArgs e) { CSVImporter csvimporter = CurrentImporter; if (e == null) { throw new ArgumentNullException("e"); } if (csvimporter == null) { lblError.Text = Resources.LogbookEntry.ImportNotSuccessful; e.Cancel = true; SetWizardStep(wsPreview); PreviewData(); // rebuild the table. return; } int cFlightsAdded = 0; int cFlightsUpdated = 0; int cFlightsWithErrors = 0; csvimporter.FCommit((le, fIsNew) => { if (String.IsNullOrEmpty(le.ErrorString)) { AddTextRow(plcProgress, String.Format(CultureInfo.CurrentCulture, fIsNew ? Resources.LogbookEntry.ImportRowAdded : Resources.LogbookEntry.ImportRowUpdated, le.ToString()), "success"); if (fIsNew) { cFlightsAdded++; } else { cFlightsUpdated++; } } else { PendingFlight pf = new PendingFlight(le) { User = User.Identity.Name }; pf.Commit(); lnkPending.Visible = true; AddTextRow(plcProgress, String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.ImportRowAddedPending, le.ToString(), le.ErrorString), "error"); cFlightsWithErrors++; } }, (le, ex) => { AddTextRow(plcProgress, String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.ImportRowNotAdded, le.ToString(), ex.Message), "error"); }, true); List <string> lstResults = new List <string>(); if (cFlightsAdded > 0) { lstResults.Add(String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.ImportFlightsAdded, cFlightsAdded)); } if (cFlightsUpdated > 0) { lstResults.Add(String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.ImportFlightsUpdated, cFlightsUpdated)); } if (cFlightsWithErrors > 0) { lstResults.Add(String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.ImportFlightsWithErrors, cFlightsWithErrors)); } rptImportResults.DataSource = lstResults; rptImportResults.DataBind(); MyFlightbook.Profile.GetUser(Page.User.Identity.Name).SetAchievementStatus(MyFlightbook.Achievements.Achievement.ComputeStatus.NeedsComputing); mvPreviewResults.SetActiveView(vwImportResults); wzImportFlights.Visible = false; pnlImportSuccessful.Visible = true; CurrentImporter = null; CurrentCSVSource = null; }
protected void Refresh() { gvPendingFlights.DataSource = Flights = PendingFlight.PendingFlightsForUser(Viewer.UserName); gvPendingFlights.DataBind(); }
protected void lnkDeleteAll_Click(object sender, EventArgs e) { PendingFlight.DeletePendingFlightsForUser(Page.User.Identity.Name); Refresh(); }
/// <summary> /// Sends the nightly/monthly emails for users that have requested it. /// </summary> private void SendNightlyEmails() { // Find all users who qualify for expiring currency notifications - they may trigger an early email. List <EarnedGratuity> lstUsersWithExpiringCurrencies = EarnedGratuity.GratuitiesForUser(null, Gratuity.GratuityTypes.CurrencyAlerts); if (!String.IsNullOrEmpty(UserRestriction)) { lstUsersWithExpiringCurrencies.RemoveAll(eg => eg.Username.CompareCurrentCultureIgnoreCase(UserRestriction) != 0); } // And the list of people who have a subscription to expiring currencies List <Profile> lstUsersSubscribedForExpiration = new List <Profile>(Profile.UsersWithSubscriptions(EmailSubscription.FlagForType(SubscriptionType.Expiration), DateTime.Now.AddDays(-7))); // get the list of people who have a subscription OTHER than simple monthly or expiration List <Profile> lstUsersToSend = new List <Profile>(Profile.UsersWithSubscriptions(~(EmailSubscription.FlagForType(SubscriptionType.MonthlyTotals) | EmailSubscription.FlagForType(SubscriptionType.Expiration)), DateTime.Now.AddDays(-7))); if (!String.IsNullOrEmpty(UserRestriction)) { lstUsersToSend.RemoveAll(pf => pf.UserName.CompareOrdinalIgnoreCase(UserRestriction) != 0); } // See who has expiring currencies that require notification. foreach (EarnedGratuity eg in lstUsersWithExpiringCurrencies) { // Skip over anybody that's not also subscribed for expiration notices Profile pf = lstUsersSubscribedForExpiration.Find(profile => profile.UserName.CompareCurrentCultureIgnoreCase(eg.Username) == 0); if (pf == null) { continue; } IEnumerable <CurrencyStatusItem> expiringCurrencies = CurrencyStatusItem.CheckForExpiringCurrencies(eg.State, eg.Username, out string newState); if (newState.CompareOrdinal(eg.State) != 0) { eg.State = newState; eg.Commit(); } if (expiringCurrencies.Any()) { if (SendMailForUser(pf, Resources.Profile.EmailCurrencyExpiringMailSubject, string.Empty)) { // Don't send the weekly mail, since we just pre-empted it. lstUsersToSend.RemoveAll(p => pf.UserName.CompareCurrentCultureIgnoreCase(eg.Username) == 0); pf.LastEmailDate = DateTime.Now; pf.FCommit(); } } } foreach (Profile pf in lstUsersToSend) { if (SendMailForUser(pf, Resources.Profile.EmailWeeklyMailSubject, String.Empty)) { pf.LastEmailDate = DateTime.Now; pf.FCommit(); } } // Now do the monthly/annual emails if (DateTime.Now.Day == 1) { lstUsersToSend = new List <Profile>(Profile.UsersWithSubscriptions(EmailSubscription.FlagForType(SubscriptionType.MonthlyTotals), DateTime.Now.AddDays(1))); // We don't update the last-email sent on this because this email is asynchronous - i.e., not dependent on any other mail that was sent. foreach (Profile pf in lstUsersToSend) { SendMailForUser(pf, String.Format(CultureInfo.CurrentCulture, Resources.Profile.EmailMonthlySubject, DateTime.Now.AddMonths(-1).ToString("MMMM", CultureInfo.InvariantCulture)), "monthly"); } } // Do a pending flights reminder - every week or so if (DateTime.Now.DayOfYear % 7 == 6) { IDictionary <string, int> usersWithPendingFlights = PendingFlight.UsersWithLotsOfPendingFlights(30); foreach (string szUser in usersWithPendingFlights.Keys) { Profile pf = Profile.GetUser(szUser); util.NotifyUser(Branding.ReBrand(Resources.Profile.PendingFlightsReminderSubject), Branding.ReBrand(String.Format(CultureInfo.CurrentCulture, Resources.Profile.PendingFlightsReminder, pf.UserFullName, usersWithPendingFlights[szUser])), new System.Net.Mail.MailAddress(pf.Email, pf.UserFullName), false, true); } } }
public override LogbookEntry ToLogbookEntry() { StringBuilder sb = new StringBuilder(); if (airports != null) { foreach (CloudAhoyAirportDescriptor ap in airports) { sb.AppendFormat(CultureInfo.CurrentCulture, "{0} ", ap.icao); } } if (aircraft == null) { aircraft = new CloudAhoyAircraftDescriptor(); } DateTime dtStart = DateTimeOffset.FromUnixTimeSeconds(time).DateTime; DictProps.Clear(); List <string> lstText = new List <string>() { MarkdownLink(remarks, url) }; PendingFlight le = new PendingFlight() { FlightID = LogbookEntry.idFlightNew, TailNumDisplay = aircraft.registration, ModelDisplay = aircraft.model, Route = sb.ToString().Trim(), TotalFlightTime = duration / 3600.0M, EngineStart = dtStart, EngineEnd = dtStart.AddSeconds(duration), Date = dtStart.Date }; PopulateCrewInfo(le); PopulateManeuvers(le, lstText); le.Comment = String.Join(" ", lstText); le.CustomProperties = PropertiesWithoutNullOrDefault(DictProps.Values).ToArray(); if (!string.IsNullOrEmpty(flightId)) { le.PendingID = flightId; } if (!String.IsNullOrEmpty(UserName)) { le.User = UserName; UserAircraft ua = new UserAircraft(UserName); Aircraft ac = ua.GetUserAircraftByTail(le.TailNumDisplay); if (ac != null) { le.AircraftID = ac.AircraftID; } } return(le); }
public override LogbookEntry ToLogbookEntry() { StringBuilder sb = new StringBuilder(); if (airports != null) { foreach (CloudAhoyAirportDescriptor ap in airports) { sb.AppendFormat(CultureInfo.CurrentCulture, "{0} ", ap.icao); } } if (aircraft == null) { aircraft = new CloudAhoyAircraftDescriptor(); } DateTime dtStart = DateTimeOffset.FromUnixTimeSeconds(time).DateTime; DictProps.Clear(); List <string> lstText = new List <string>() { MarkdownLink(remarks, link) }; PendingFlight le = new PendingFlight() { FlightID = LogbookEntry.idFlightNew, TailNumDisplay = aircraft.registration, ModelDisplay = aircraft.model, Route = sb.ToString().Trim(), TotalFlightTime = duration / 3600.0M, EngineStart = dtStart, EngineEnd = dtStart.AddSeconds(duration), Date = dtStart.Date }; PopulateCrewInfo(le); PopulateManeuvers(le, lstText); le.Comment = String.Join(" ", lstText); if (!string.IsNullOrEmpty(flightId)) { le.PendingID = flightId; } if (!String.IsNullOrEmpty(UserName)) { le.User = UserName; Aircraft ac = BestGuessAircraftID(UserName, le.TailNumDisplay); if (ac != null) { le.AircraftID = ac.AircraftID; if (ac.IsAnonymous) { DictProps[CustomPropertyType.KnownProperties.IDPropAircraftRegistration] = CustomFlightProperty.PropertyWithValue(CustomPropertyType.KnownProperties.IDPropAircraftRegistration, le.TailNumDisplay); } } } le.CustomProperties.SetItems(DictProps.Values); return(le); }