using Elwig.Helpers; using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; namespace Elwig.Windows { public abstract class AdministrationWindow : ContextWindow { protected Control[] ExemptInputs { private get; set; } protected Control[] RequiredInputs { private get; set; } private TextBox[] TextBoxInputs; private ComboBox[] ComboBoxInputs; private CheckBox[] CheckBoxInputs; private RadioButton[] RadioButtonInputs; private readonly Dictionary Valid; private readonly Dictionary OriginalValues; public AdministrationWindow() : base() { ExemptInputs = Array.Empty(); RequiredInputs = Array.Empty(); TextBoxInputs = Array.Empty(); ComboBoxInputs = Array.Empty(); CheckBoxInputs = Array.Empty(); RadioButtonInputs = Array.Empty(); Valid = new(); OriginalValues = new(); Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs evt) { TextBoxInputs = Utils.FindAllChildren(this, ExemptInputs).ToArray(); ComboBoxInputs = Utils.FindAllChildren(this, ExemptInputs).ToArray(); CheckBoxInputs = Utils.FindAllChildren(this, ExemptInputs).ToArray(); RadioButtonInputs = Utils.FindAllChildren(this, ExemptInputs).ToArray(); foreach (var tb in TextBoxInputs) Valid[tb] = true; } abstract protected void UpdateButtons(); protected void ValidateInput(Control input, bool valid) { Valid[input] = valid; } protected bool SenderIsRequired(object sender) { return (sender is Control c) && RequiredInputs.Contains(c); } protected void ClearInputStates() { foreach (var tb in TextBoxInputs) Utils.ClearInputState(tb); foreach (var cb in ComboBoxInputs) Utils.ClearInputState(cb); foreach (var cb in CheckBoxInputs) Utils.ClearInputState(cb); foreach (var rb in RadioButtonInputs) Utils.ClearInputState(rb); } protected void ValidateRequiredInputs() { foreach (var input in RequiredInputs) { if (input is TextBox tb && tb.Text.Length == 0) { Utils.SetInputInvalid(input); Valid[input] = false; } else if (input is ComboBox cb && cb.SelectedItem == null && cb.ItemsSource != null) { Utils.SetInputInvalid(input); } } } protected void LockInputs() { foreach (var tb in TextBoxInputs) tb.IsReadOnly = true; foreach (var cb in ComboBoxInputs) cb.IsEnabled = false; foreach (var cb in CheckBoxInputs) cb.IsEnabled = false; foreach (var rb in RadioButtonInputs) rb.IsEnabled = false; } protected void UnlockInputs() { foreach (var tb in TextBoxInputs) tb.IsReadOnly = false; foreach (var cb in ComboBoxInputs) cb.IsEnabled = true; foreach (var cb in CheckBoxInputs) cb.IsEnabled = true; foreach (var rb in RadioButtonInputs) rb.IsEnabled = true; } protected void ClearOriginalValues() { OriginalValues.Clear(); } protected void FillOriginalValues() { foreach (var tb in TextBoxInputs) OriginalValues[tb] = tb.Text; foreach (var cb in ComboBoxInputs) OriginalValues[cb] = cb.SelectedItem; foreach (var cb in CheckBoxInputs) OriginalValues[cb] = (cb.IsChecked ?? false) ? bool.TrueString : null; foreach (var rb in RadioButtonInputs) OriginalValues[rb] = (rb.IsChecked ?? false) ? bool.TrueString : null; } protected void ClearInputs() { foreach (var tb in TextBoxInputs) tb.Text = ""; foreach (var cb in ComboBoxInputs) cb.SelectedItem = null; foreach (var cb in CheckBoxInputs) cb.IsChecked = false; foreach (var rb in RadioButtonInputs) rb.IsChecked = false; ValidateRequiredInputs(); } protected bool IsValid() { return Valid.All(kv => kv.Value) && ComboBoxInputs.All(cb => cb.ItemsSource == null || cb.SelectedItem != null); } protected bool InputHasChanged(Control input) { if (!OriginalValues.ContainsKey(input)) { return false; } else if (input is TextBox tb) { return OriginalValues[tb]?.ToString() != tb.Text; } else if (input is ComboBox sb) { return OriginalValues[sb] != sb.SelectedItem; } else if (input is CheckBox cb) { return (OriginalValues[cb] != null) != (cb.IsChecked ?? false); } else if (input is RadioButton rb) { return (OriginalValues[rb] != null) != (rb.IsChecked ?? false); } else { return false; } } protected bool HasChanged() { return !IsValid() || TextBoxInputs.Any(InputHasChanged) || ComboBoxInputs.Any(InputHasChanged) || CheckBoxInputs.Any(InputHasChanged) || RadioButtonInputs.Any(InputHasChanged); } protected void UpdatePlz(TextBox plzInput, ComboBox ortInput) { if (plzInput.Text.Length == 4) { ortInput.ItemsSource = Context.Postleitzahlen.Find(int.Parse(plzInput.Text))?.Orte.ToList(); } else { ortInput.ItemsSource = null; } ortInput.SelectedItem = null; if (ortInput.ItemsSource != null) { Utils.SetInputInvalid(ortInput); } else { Utils.ClearInputState(ortInput); } ValidateInput(plzInput, SenderIsRequired(plzInput) || (ortInput.ItemsSource != null)); UpdateButtons(); } protected void InputTextChanged(TextBox input, Func checker) { InputTextChanged(input, (tb, required, ctx) => checker(tb, required)); } protected void InputTextChanged(TextBox input, Func checker) { InputTextChanged(input, checker(input, SenderIsRequired(input), Context)); } protected void InputTextChanged(TextBox input, ValidationResult res) { ValidateInput(input, res.IsValid); if (res.IsValid) { if (InputHasChanged(input)) { Utils.SetInputChanged(input); } else { Utils.ClearInputState(input); } } else { Utils.SetInputInvalid(input); } UpdateButtons(); } protected void InputLostFocus(TextBox input, Func checker, string? msg = null) { InputLostFocus(input, (tb, requiered, ctx) => checker(tb, requiered), msg); } protected void InputLostFocus(TextBox input, Func checker, string? msg = null) { InputLostFocus(input, checker(input, SenderIsRequired(input), Context), msg); } protected void InputLostFocus(TextBox input, ValidationResult res, string? msg = null) { if (!res.IsValid) MessageBox.Show(res.ErrorContent.ToString(), msg ?? res.ErrorContent.ToString(), MessageBoxButton.OK, MessageBoxImage.Warning); } protected void CheckBox_Changed(object sender, RoutedEventArgs evt) { var input = (CheckBox)sender; if (SenderIsRequired(input) && input.IsChecked != true) { Utils.SetInputInvalid(input); } else if (InputHasChanged(input)) { Utils.SetInputChanged(input); } else { Utils.ClearInputState(input); } UpdateButtons(); } protected void RadioButton_Changed(object sender, RoutedEventArgs evt) { var input = (RadioButton)sender; if (SenderIsRequired(input) && input.IsChecked != true) { Utils.SetInputInvalid(input); } else if (InputHasChanged(input)) { Utils.SetInputChanged(input); } else { Utils.ClearInputState(input); } UpdateButtons(); } protected void TextBox_TextChanged(object sender, RoutedEventArgs evt) { var input = (TextBox)sender; if (SenderIsRequired(input) && input.Text.Length == 0) { ValidateInput(input, false); Utils.SetInputInvalid(input); } else { ValidateInput(input, true); if (InputHasChanged(input)) { Utils.SetInputChanged(input); } else { Utils.ClearInputState(input); } } UpdateButtons(); } protected void ComboBox_SelectionChanged(object sender, RoutedEventArgs evt) { var input = (ComboBox)sender; if (input.ItemsSource != null && input.SelectedItem == null) { Utils.SetInputInvalid(input); } else if (InputHasChanged(input)) { Utils.SetInputChanged(input); } else { Utils.ClearInputState(input); } UpdateButtons(); } protected void IntegerInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckInteger); } protected void PartialDateInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckPartialDate); } protected void DateInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckDate); } protected void PlzInput_TextChanged(object sender, RoutedEventArgs evt) { var plz = (TextBox)sender; InputTextChanged(plz, Validator.CheckPlz); UpdatePlz(plz, Utils.FindNextSibling(plz)); } protected void PlzInput_LostFocus(object sender, RoutedEventArgs evt) { var plz = (TextBox)sender; InputLostFocus(plz, Validator.CheckPlz); UpdatePlz(plz, Utils.FindNextSibling(plz)); } protected void EmailInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckEmailAddress); } protected void EmailInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckEmailAddress); } protected void PhoneNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckPhoneNumber); } protected void PhoneNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckPhoneNumber); } protected void IbanInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckIban); } protected void IbanInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckIban); } protected void BicInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckBic); } protected void BicInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckBic); } protected void UstIdInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckUstId); } protected void UstIdInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckUstId); } protected void LfbisNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckLfbisNr); } protected void LfbisNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckLfbisNr); } } }