using InABox.Core; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using Xceed.Wpf.Toolkit.PropertyGrid.Converters; namespace InABox.DynamicGrid { public delegate void FieldChangedEvent(); public interface IDynamicFormFieldControl { public event FieldChangedEvent? FieldChangedEvent; void Deserialize(DFLoadStorageEntry storage); void Serialize(DFSaveStorageEntry storage); public object? GetValue(); /// /// Sets the value in this control. /// /// The value to set. This will be the return value from a call to . public void SetValue(object? value); public object? GetEntityValue(); public void SetEntityValue(object? value); /// /// Gets additional data for this field by the specific field name of . /// /// A name which specifies what data is requested. /// The additional data. public object? GetData(string field); /// /// Gets additional data for this field that should be saved into the form data. /// /// The additional data. public Dictionary? GetAdditionalValues(); /// /// Check that the data is valid - if it is not, output a message for the user. /// This function gets called when the user completes a form, or edits an already completed form. /// /// The message to the user. /// if the data is valid. public bool Validate([NotNullWhen(false)] out string? message); } public abstract class DynamicFormFieldControl : DynamicFormControl, IDynamicFormFieldControl where TField : DFLayoutField where TProperties : DFLayoutFieldProperties, new() { public event FieldChangedEvent? FieldChangedEvent; public TField Field { get => Control; set => Control = value; } public void Serialize(DFSaveStorageEntry storage) { Field.Properties.SerializeValue(storage, GetSerializedValue()); } public void Deserialize(DFLoadStorageEntry storage) { SetSerializedValue(Field.Properties.DeserializeValue(storage)); } protected void ChangeField() => FieldChangedEvent?.Invoke(); /// /// Checks whether the user has supplied a field - for use with . /// /// if the user has not supplied a value. protected abstract bool IsEmpty(); public virtual bool Validate([NotNullWhen(false)] out string? message) { if(Field.Properties.Required && IsEmpty()) { message = $"Field [{Field.Name}] is required!"; return false; } message = null; return true; } protected override void AfterSetControl(TField control) { base.AfterSetControl(control); if (!string.IsNullOrWhiteSpace(control.Properties.Expression) || control.Properties.ReadOnlyProperty) { IsEnabled = false; } } public abstract TSerialized GetSerializedValue(); public abstract void SetSerializedValue(TSerialized value); public abstract TValue GetValue(); public abstract void SetValue(TValue? value); public virtual object? GetEntityValue() => GetValue(); public virtual void SetEntityValue(object? value) => SetValue(CoreUtils.ChangeType(value)); public virtual object? GetData(string dataField) { return null; } public virtual Dictionary? GetAdditionalValues() { return null; } object? IDynamicFormFieldControl.GetValue() => GetValue(); void IDynamicFormFieldControl.SetValue(object? value) => SetValue(value != null ? (TValue)value : default); } }