瀏覽代碼

Made DF boolean fields able to be null and fixed default values for options field controls

Kenric Nugteren 1 月之前
父節點
當前提交
04d72fb23f

+ 16 - 6
InABox.Core/DigitalForms/Layouts/Fields/DFLayoutBooleanField/DFLayoutBooleanFieldProperties.cs

@@ -7,12 +7,12 @@
         Buttons
     }
 
-    public class DFLayoutBooleanFieldProperties : DFLayoutFieldProperties<bool, bool?>
+    public class DFLayoutBooleanFieldProperties : DFLayoutFieldProperties<bool?, bool?>
     {
         
         [EditorSequence(-995)]
         [CheckBoxEditor]
-        public override bool Default { get; set; }
+        public override bool? Default { get; set; }
         
         [EnumLookupEditor(typeof(DesignBooleanFieldType))]
         [EditorSequence(1)]
@@ -44,10 +44,15 @@
 
         public override string FormatValue(bool? value)
         {
-            return value == true ? TrueValue : FalseValue;
+            return value switch
+            {
+                true => TrueValue,
+                false => FalseValue,
+                null => ""
+            };
         }
 
-        public override bool GetValue(bool? value)
+        public override bool? GetValue(bool? value)
         {
             return value ?? Default;
         }
@@ -63,9 +68,10 @@
             {
                 if (str == TrueValue)
                     return true;
-                if (str == FalseValue)
+                else if (str == FalseValue)
                     return false;
-                return null;
+                else
+                    return null;
             }
             return null;
         }
@@ -80,6 +86,10 @@
             {
                 entry.SetValue(FalseValue);
             }
+            else
+            {
+                entry.SetValue(null);
+            }
         }
     }
 }

+ 53 - 34
inabox.wpf/DigitalForms/Designer/Controls/Fields/DFBooleanControl.cs

@@ -5,50 +5,69 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 
-namespace InABox.DynamicGrid
+namespace InABox.DynamicGrid;
+
+public class DFBooleanControl : DynamicFormFieldControl<DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool?, bool?>
 {
-    public class DFBooleanControl : DynamicFormFieldControl<DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool, bool?>
-    {
-        private IOptionControl OptionControl = null!; // Late-initialised
+    private IOptionControl OptionControl = null!; // Late-initialised
 
-        protected override FrameworkElement Create()
+    protected override FrameworkElement Create()
+    {
+        var options = new[] { Field.Properties.TrueValue, Field.Properties.FalseValue };
+        var defValue = Field.Properties.Default switch
         {
-            var options = new[] { Field.Properties.TrueValue, Field.Properties.FalseValue };
-            switch (Field.Properties.Type)
-            {
-                case DesignBooleanFieldType.Buttons:
-                    return SetControl(new ButtonsOptionControl(options, ChangeField));
-                case DesignBooleanFieldType.ComboBox:
-                    return SetControl(new ComboBoxOptionControl(options, ChangeField));
-            }
-            return SetControl(new CheckBoxOptionControl(Field.Properties.TrueValue, Field.Properties.FalseValue, ChangeField));
-        }
+            true => Field.Properties.TrueValue,
+            false => Field.Properties.FalseValue,
+            null => null
+        };
+        return Field.Properties.Type switch
+        {
+            DesignBooleanFieldType.Buttons => SetControl(new ButtonsOptionControl(options, ChangeField, defValue)),
+            DesignBooleanFieldType.ComboBox => SetControl(new ComboBoxOptionControl(options, ChangeField, defValue)),
+            DesignBooleanFieldType.Checkbox or _ => SetControl(new CheckBoxOptionControl(Field.Properties.TrueValue, Field.Properties.FalseValue, ChangeField, Field.Properties.Required, Field.Properties.Default)),
+        };
+    }
+
+    private T SetControl<T>(T value)
+        where T : FrameworkElement, IOptionControl
+    {
+        OptionControl = value;
+        return value;
+    }
+
+    public override bool? GetSerializedValue()
+    {
+        return GetValue();
+    }
+
+    public override void SetSerializedValue(bool? value)
+    {
+        SetValue(value);
+    }
 
-        private T SetControl<T>(T value)
-            where T : FrameworkElement, IOptionControl
+    public override bool? GetValue()
+    {
+        var val = OptionControl.GetValue();
+        if(val == Field.Properties.TrueValue)
         {
-            OptionControl = value;
-            return value;
+            return true;
         }
-
-        public override bool? GetSerializedValue()
+        else if(val == Field.Properties.FalseValue)
         {
-            return GetValue();
+            return false;
         }
-
-        public override void SetSerializedValue(bool? value)
+        else
         {
-            SetValue(value ?? false);
+            return null;
         }
+    }
 
-        public override bool GetValue() => OptionControl.GetValue() == Field.Properties.TrueValue;
-
-        public override void SetValue(bool value) => OptionControl.SetValue(value ? Field.Properties.TrueValue : Field.Properties.FalseValue);
+    public override void SetValue(bool? value) => OptionControl.SetValue(value switch
+    {
+        true => Field.Properties.TrueValue,
+        false => Field.Properties.FalseValue,
+        null => null
+    });
 
-        protected override bool IsEmpty() => Field.Properties.Type switch
-        {
-            DesignBooleanFieldType.Checkbox => GetValue() != true,
-            _ => OptionControl.IsEmpty()
-        };
-    }
+    protected override bool IsEmpty() => OptionControl.IsEmpty();
 }

+ 37 - 27
inabox.wpf/DigitalForms/Designer/Controls/Fields/DFOptionControl.cs

@@ -13,8 +13,7 @@ namespace InABox.DynamicGrid;
 public interface IOptionControl
 {
     public string? GetValue();
-    public void SetValue(string value);
-
+    public void SetValue(string? value);
     public bool IsEmpty();
 }
 
@@ -52,14 +51,14 @@ public class ButtonsOptionControl : Grid, IOptionControl
         }
     }
 
-    public ButtonsOptionControl(string[] options, Action onChanged)
+    public ButtonsOptionControl(string[] options, Action onChanged, string? defValue)
     {
         OnChanged = onChanged;
 
         foreach (var option in options)
         {
             ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
-            var button = new OptionButton(option, false);
+            var button = new OptionButton(option, option == defValue);
 
             var label = new Label()
             {
@@ -127,7 +126,7 @@ public class ButtonsOptionControl : Grid, IOptionControl
         return null;
     }
 
-    public void SetValue(string value)
+    public void SetValue(string? value)
     {
         var found = false;
         foreach (var child in Children)
@@ -154,7 +153,7 @@ public class RadioOptionControl : Grid, IOptionControl
 {
     private Action OnChanged;
 
-    public RadioOptionControl(string[] options, Action onChanged)
+    public RadioOptionControl(string[] options, Action onChanged, string? defValue)
     {
         Margin = new Thickness(4,2,4,2);
         
@@ -170,6 +169,7 @@ public class RadioOptionControl : Grid, IOptionControl
             button.Padding = new Thickness(5.0F, 0.0F, 5.0F, 0.0F);
             button.SetValue(RowProperty, Children.Count);
             button.Tag = option;
+            button.IsChecked = option == defValue;
             button.Checked += Button_Checked;
             button.Unchecked += Button_Checked;
             Children.Add(button);
@@ -196,7 +196,7 @@ public class RadioOptionControl : Grid, IOptionControl
         return null;
     }
 
-    public void SetValue(string value)
+    public void SetValue(string? value)
     {
         var found = false;
         foreach (var child in Children)
@@ -228,7 +228,7 @@ public class ComboBoxOptionControl : ComboBox, IOptionControl
 {
     private readonly Action OnChanged;
 
-    public ComboBoxOptionControl(string[] options, Action onChanged)
+    public ComboBoxOptionControl(string[] options, Action onChanged, string? defValue)
     {
         SetResourceReference(StyleProperty, typeof(ComboBox));
 
@@ -236,6 +236,7 @@ public class ComboBoxOptionControl : ComboBox, IOptionControl
 
         foreach (var option in options)
             Items.Add(option);
+        SelectedValue = defValue;
         VerticalContentAlignment = VerticalAlignment.Center;
         SelectionChanged += ComboBoxOptionControl_SelectionChanged;
     }
@@ -250,7 +251,7 @@ public class ComboBoxOptionControl : ComboBox, IOptionControl
         return SelectedValue as string;
     }
 
-    public void SetValue(string value)
+    public void SetValue(string? value)
     {
         SelectedValue = value;
     }
@@ -264,13 +265,17 @@ public class CheckBoxOptionControl : CheckBox, IOptionControl
     private readonly string TrueValue;
     private readonly string FalseValue;
 
-    public CheckBoxOptionControl(string trueValue, string falseValue, Action onChanged)
+    private bool? _value;
+    private bool Required;
+
+    public CheckBoxOptionControl(string trueValue, string falseValue, Action onChanged, bool required, bool? defValue)
     {
         OnChanged = onChanged;
         TrueValue = trueValue;
         FalseValue = falseValue;
+        Required = required;
 
-        IsThreeState = false;
+        IsChecked = defValue ?? (required ? null : false);
         HorizontalContentAlignment = HorizontalAlignment.Center;
         VerticalContentAlignment = VerticalAlignment.Center;
         Checked += CheckBoxOptionControl_Checked;
@@ -279,22 +284,29 @@ public class CheckBoxOptionControl : CheckBox, IOptionControl
 
     private void CheckBoxOptionControl_Checked(object sender, RoutedEventArgs e)
     {
+        _value = IsChecked;
         OnChanged();
     }
 
     public string? GetValue()
     {
-        return IsChecked == true
-            ? TrueValue
-            : FalseValue;
+        return _value switch
+        {
+            true => TrueValue,
+            false => FalseValue,
+            null => null
+        };
     }
 
-    public void SetValue(string value)
+    public void SetValue(string? value)
     {
-        IsChecked = value == TrueValue;
+        _value = value == TrueValue ? true
+            : value == FalseValue ? false
+            : null;
+        IsChecked = Required ? _value : (_value ?? false);
     }
 
-    public bool IsEmpty() => false;
+    public bool IsEmpty() => IsChecked is null;
 }
 
 public class DFOptionControl : DynamicFormFieldControl<DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>
@@ -304,17 +316,15 @@ public class DFOptionControl : DynamicFormFieldControl<DFLayoutOptionField, DFLa
     protected override FrameworkElement Create()
     {
         var options = string.IsNullOrWhiteSpace(Field.Properties.Options) 
-            ? new string[] { } 
-            : Field.Properties.Options.Replace(",","\n").Split('\n').Select(x=>x.Trim()).ToArray();
+            ? []
+            : Field.Properties.Options.Replace(",","\n").Split('\n').ToArray(x => x.Trim());
 
-        switch (Field.Properties.OptionType)
+        return Field.Properties.OptionType switch
         {
-            case DFLayoutOptionType.Buttons:
-                return SetControl(new ButtonsOptionControl(options, ChangeField));
-            case DFLayoutOptionType.Radio:
-                return SetControl(new RadioOptionControl(options, ChangeField));
-        }
-        return SetControl(new ComboBoxOptionControl(options, ChangeField));
+            DFLayoutOptionType.Buttons => SetControl(new ButtonsOptionControl(options, ChangeField, Field.Properties.Default)),
+            DFLayoutOptionType.Radio => SetControl(new RadioOptionControl(options, ChangeField, Field.Properties.Default)),
+            _ => SetControl(new ComboBoxOptionControl(options, ChangeField, Field.Properties.Default)),
+        };
     }
 
     private T SetControl<T>(T value)
@@ -336,7 +346,7 @@ public class DFOptionControl : DynamicFormFieldControl<DFLayoutOptionField, DFLa
 
     public override string GetValue() => OptionControl.GetValue() ?? "";
 
-    public override void SetValue(string? value) => OptionControl.SetValue(value ?? "");
+    public override void SetValue(string? value) => OptionControl.SetValue(value);
 
     protected override bool IsEmpty() => OptionControl.IsEmpty();
 }