// Copyright (c) 2017 schick Informatik // Description: Basisklasse für die Detailansichten. Hier sollten Dinge wie Validierung etc. abgehandelt werden // using System; using System.Collections.Generic; using System.ComponentModel; using System.Text.RegularExpressions; using System.Windows.Controls; using Xceed.Wpf.Toolkit; using bsmd.database; using ENI2.Util; using ENI2.Controls; namespace ENI2 { public class DetailBaseControl : UserControl, IHighlightControlContainer { #region Fields protected bool _initialized = false; private DependencyPropertyDescriptor _dpTextBox; private DependencyPropertyDescriptor _dpDateTimePicker; private DependencyPropertyDescriptor _dpDatePicker; private DependencyPropertyDescriptor _dpLocode; private DependencyPropertyDescriptor _dpCheckbox; private DependencyPropertyDescriptor _dpComboboxIndex; private DependencyPropertyDescriptor _dpComboboxValue; private DependencyPropertyDescriptor _dpNumericUpdown; private DependencyPropertyDescriptor _dpIntUpdown; private readonly Dictionary _controlClassDict = new Dictionary(); private readonly Dictionary _typeMessageDict = new Dictionary(); private static readonly Regex rdt = new Regex(@"^(\d{12})$"); private static readonly Regex rd = new Regex(@"^(\d{8})$"); #endregion #region enum protected enum LocodeState { UNKNOWN, INVALID, OK, AMBIGUOUS } #endregion #region events /// /// Mit diesem event kann ein Listenelement den programmatischen Sprung auf ein anderes Listenelement auslösen /// (das wird zunächst nur vom Overview -> Auswahl Meldeklasse verwendet) /// public event Action JumpToListElementRequest; /// /// Mit diesem Event kann ein Listen-Element einen Reload der gesamten Anmeldung auslösen /// public event Action RequestReload; /// /// Damit kann ein Listenelement eine Validierung der gesamten Anmeldung auslösen (inkl. Highlighting) (auf Knopfdruck) /// public event Action RequestValidate; /// /// Alle Meldeklassen die auf "zu versenden" stehen werden validiert und falls die Validierung scheitert auf "SUSPEND" gestellt /// public event Action RequestSendValidation; /// /// Damit kann signalisiert werden, dass die Anmeldung readonly wird (z.B. bei Storno) /// public event Action RequestDisable; /// /// Damit kann aus einer Anmeldung heraus die Kopier-Logik ausgelöst werden /// public event Action RequestCopy; /// /// Eine in der Detailansicht enthaltene Meldeklasse hat sich geändert /// public event Action NotificationClassChanged; /// /// Eine Maske soll neu erzeugt werden weil sich dort "indirekt" etwas geändert hat durch eine Änderung in einer anderen Maske. /// (Beispiel Copy HAZA nach HAZD Elemente) /// public event Action ResetControlCache; #endregion #region Properties /// /// Core to be edited /// public MessageCore Core { get; set; } /// /// all messages for this core /// public List Messages { get; set; } /// /// particular messages that are edited on this page /// public List ControlMessages { get; } = new List(); public bool LockedByOtherUser { get; set; } #endregion #region public methods public virtual void Initialize() { _dpTextBox = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox)); _dpDateTimePicker = DependencyPropertyDescriptor.FromProperty(Xceed.Wpf.Toolkit.DateTimePicker.ValueProperty, typeof(Xceed.Wpf.Toolkit.DateTimePicker)); _dpDatePicker = DependencyPropertyDescriptor.FromProperty(DatePicker.SelectedDateProperty, typeof(DatePicker)); _dpLocode = DependencyPropertyDescriptor.FromProperty(Controls.LocodeControl.LocodeValueProperty, typeof(Controls.LocodeControl)); _dpCheckbox = DependencyPropertyDescriptor.FromProperty(CheckBox.IsCheckedProperty, typeof(CheckBox)); _dpComboboxIndex = DependencyPropertyDescriptor.FromProperty(ComboBox.SelectedIndexProperty, typeof(ComboBox)); _dpComboboxValue = DependencyPropertyDescriptor.FromProperty(ComboBox.SelectedValueProperty, typeof(ComboBox)); _dpNumericUpdown = DependencyPropertyDescriptor.FromProperty(Xceed.Wpf.Toolkit.DoubleUpDown.ValueProperty, typeof(Xceed.Wpf.Toolkit.DoubleUpDown)); _dpIntUpdown = DependencyPropertyDescriptor.FromProperty(Xceed.Wpf.Toolkit.IntegerUpDown.ValueProperty, typeof(Xceed.Wpf.Toolkit.IntegerUpDown)); foreach(Message message in this.Messages) { _typeMessageDict[message.MessageNotificationClass] = message; } } public virtual void SetEnabled(bool enabled) { this.IsEnabled = enabled; } #endregion #region protected methods protected virtual void OnJumpToListElementRequest(int index) { this.JumpToListElementRequest?.Invoke(index); } protected virtual void OnRequestReload(Guid coreId) { this.RequestReload?.Invoke(coreId); } protected virtual void OnRequestValidate() { this.RequestValidate?.Invoke(); } protected virtual void OnRequestSendValidation() { this.RequestSendValidation?.Invoke(); } protected virtual void OnRequestDisable() { this.RequestDisable?.Invoke(); } protected virtual void OnRequestCopy() { this.RequestCopy?.Invoke(); } protected virtual void OnControlCacheReset(string messageGroupName) { this.ResetControlCache?.Invoke(messageGroupName); } protected virtual void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) { ScrollViewer scv = (ScrollViewer)sender; scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta); e.Handled = true; } #region event handling for control content changes (signal dirty etc) protected void RegisterTextboxChange(TextBox textBox, Message.NotificationClass notificationClass) { this._dpTextBox.AddValueChanged(textBox, this.controlContentChanged); this._controlClassDict[textBox] = notificationClass; } protected void UnregisterTextboxChange(TextBox textBox) { this._dpTextBox.RemoveValueChanged(textBox, this.controlContentChanged); if (this._controlClassDict.ContainsKey(textBox)) this._controlClassDict.Remove(textBox); } protected void RegisterDateTimePickerChange(Xceed.Wpf.Toolkit.DateTimePicker dateTimePicker, Message.NotificationClass notificationClass) { this._dpDateTimePicker.AddValueChanged(dateTimePicker, this.controlContentChanged); this._controlClassDict[dateTimePicker] = notificationClass; } protected void RegisterDatePickerChange(DatePicker datePicker, Message.NotificationClass notificationClass) { this._dpDatePicker.AddValueChanged(datePicker, this.controlContentChanged); this._controlClassDict[datePicker] = notificationClass; } protected void RegisterLocodeChange(Controls.LocodeControl locodeControl, Message.NotificationClass notificationClass) { this._dpLocode.AddValueChanged(locodeControl, this.controlContentChanged); this._controlClassDict[locodeControl] = notificationClass; } protected void RegisterCheckboxChange(CheckBox checkBox, Message.NotificationClass notificationClass) { this._dpCheckbox.AddValueChanged(checkBox, this.controlContentChanged); this._controlClassDict[checkBox] = notificationClass; } protected void RegisterComboboxIndexChange(ComboBox comboBox, Message.NotificationClass notificationClass) { this._dpComboboxIndex.AddValueChanged(comboBox, this.controlContentChanged); this._controlClassDict[comboBox] = notificationClass; } protected void RegisterComboboxValueChange(ComboBox comboBox, Message.NotificationClass notificationClass) { this._dpComboboxValue.AddValueChanged(comboBox, this.controlContentChanged); this._controlClassDict[comboBox] = notificationClass; } protected void RegisterDoubleUpDownChange(Xceed.Wpf.Toolkit.DoubleUpDown doubleUpDown, Message.NotificationClass notificationClass) { this._dpNumericUpdown.AddValueChanged(doubleUpDown, this.controlContentChanged); this._controlClassDict[doubleUpDown] = notificationClass; } protected void RegisterIntegerUpDownChange(Xceed.Wpf.Toolkit.IntegerUpDown intUpDown, Message.NotificationClass notificationClass) { this._dpIntUpdown.AddValueChanged(intUpDown, this.controlContentChanged); this._controlClassDict[intUpDown] = notificationClass; } protected void SublistElementChanged(Message.NotificationClass notificationClass) { if (_typeMessageDict.ContainsKey(notificationClass)) { if (!_typeMessageDict[notificationClass].IsDirty) { if (!_typeMessageDict[notificationClass].IsDirty) { _typeMessageDict[notificationClass].IsDirty = true; // signal this notification class changed.. this.OnNotificationClassChanged(notificationClass); } } } } protected void OnNotificationClassChanged(Message.NotificationClass? notificationClass) { this.NotificationClassChanged?.Invoke(notificationClass); } #region "BHV Spezial" Datetime Parsing.. protected void DateTimePicker_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e) { if ((sender is DateTimePicker thePicker) && rdt.IsMatch(thePicker.Text)) { try { string timevalText = rdt.Match(thePicker.Text).Captures[0].Value; int day = Int32.Parse(timevalText.Substring(0, 2)); int month = Int32.Parse(timevalText.Substring(2, 2)); int year = Int32.Parse(timevalText.Substring(4, 4)); int hour = Int32.Parse(timevalText.Substring(8, 2)); int minute = Int32.Parse(timevalText.Substring(10, 2)); thePicker.Value = new DateTime(year, month, day, hour, minute, 0); } catch (Exception) { thePicker.Value = null; } } } protected void DateTimePicker_PreviewKeyUpDate(object sender, System.Windows.Input.KeyEventArgs e) { if ((sender is DatePicker thePicker) && rd.IsMatch(thePicker.Text)) { try { string timevalText = rd.Match(thePicker.Text).Captures[0].Value; int day = Int32.Parse(timevalText.Substring(0, 2)); int month = Int32.Parse(timevalText.Substring(2, 2)); int year = Int32.Parse(timevalText.Substring(4, 4)); thePicker.SelectedDate = new DateTime(year, month, day, 0, 0, 0); } catch (Exception) { thePicker.SelectedDate = null; } } } #endregion #endregion #region private private void controlContentChanged(object ctrl, EventArgs args) { if (this._controlClassDict.ContainsKey(ctrl)) { Message.NotificationClass notificationClass = this._controlClassDict[ctrl]; this.SublistElementChanged(notificationClass); } else { System.Diagnostics.Trace.WriteLine("no notification class registered for control!!"); } } #endregion #region combobox content filtering protected void ComboBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) { ComboBox cmb = sender as ComboBox; GlobalStructures.FilterCombobox(cmb, e.Key); } #endregion #endregion #region IHighlightControlContainer implementation public virtual void HighlightErrorMessageContainer() { //throw new NotImplementedException(); } public virtual void HighlightViolationMessageContainer() { //throw new NotImplementedException(); } public virtual void HighlightProperty(Message theMessage, string propertyName, string identifier, HighlightService.HighlightStyle style) { throw new NotImplementedException(); } #endregion } }