如何使PXDBTimeSpanLongAttribute支持负时长的输入与显示?
Absolutely! I’ve worked through this exact requirement in Acumatica before, and building a custom attribute that extends PXDBTimeSpanLongAttribute is the perfect solution. Below is a complete implementation that supports negative duration values for both display (converting stored total minutes to a readable format like -HH:mm) and user input (parsing negative time strings back to total minutes):
using PX.Data; using System; public class PXDBTimeSpanLongWithNegativeAttribute : PXDBTimeSpanLongAttribute { public PXDBTimeSpanLongWithNegativeAttribute() : base() { // Retain base attribute behavior while overriding formatting/parsing logic } public override void FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e) { base.FieldSelecting(cache, e); if (e.ReturnValue is int totalMinutes) { // Handle negative values by calculating absolute minutes first bool isNegative = totalMinutes < 0; int absMinutes = Math.Abs(totalMinutes); int hours = absMinutes / 60; int minutes = absMinutes % 60; // Format with negative sign if needed, ensuring 2-digit hours/minutes e.ReturnValue = $"{(isNegative ? "-" : "")}{hours:D2}:{minutes:D2}"; } } public override void FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e) { if (e.NewValue is string inputString && !string.IsNullOrEmpty(inputString)) { bool isNegative = inputString.StartsWith("-"); string cleanInput = isNegative ? inputString.TrimStart('-') : inputString; // Parse the time string in HH:mm format if (TimeSpan.TryParse(cleanInput, out TimeSpan parsedTime)) { int totalMinutes = (int)parsedTime.TotalMinutes; // Apply negative sign if the input included one e.NewValue = isNegative ? -totalMinutes : totalMinutes; } else { // Custom error handling for invalid input throw new PXSetPropertyException("Invalid time format. Use HH:mm with optional negative sign (e.g., -01:30)."); } } base.FieldUpdating(cache, e); } }
Key Details About This Implementation:
- Display Logic: Overrides
FieldSelectingto convert stored integer minutes (positive or negative) into a user-friendlyHH:mmformat, adding a negative sign when the total minutes are negative. - Input Parsing: Overrides
FieldUpdatingto recognize negative signs in user input, parse the time string, convert back to total minutes, and apply the negative value before storing. - Error Handling: Includes basic validation for invalid input formats, which you can adjust to match your application's specific error handling standards.
How to Use This Attribute:
Apply it to your DAC field that stores total minutes as a PXDBInt type, just like you would use the standard PXDBTimeSpanLongAttribute:
public class YourDAC : IBqlTable { // ... other DAC fields ... [PXDBInt] [PXUIField(DisplayName = "Duration (Minutes)")] [PXDBTimeSpanLongWithNegativeAttribute] // Use our custom attribute public virtual int? DurationMinutes { get; set; } public abstract class durationMinutes : PX.Data.BQL.BqlInt.Field<durationMinutes> { } }
This setup will let users see negative durations formatted correctly (e.g., -02:15 for -135 minutes) and input negative times directly (like -01:45 which gets stored as -105 minutes).
内容的提问来源于stack exchange,提问作者Brendan

