using FasdDesktopUi.Basics.Helper; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using static C4IT.Logging.cLogManager; namespace FasdDesktopUi.Basics.Models { public interface IFocusInvoker { int? ParentIndex { get; } UIElement ParentElement { get; } } public static class cFocusInvoker { public static EventHandler GotFocus = delegate { }; public static EventHandler LostFocus = delegate { }; private static void ReAllocate(this IFocusInvoker focusInvoker) { try { if (!(focusInvoker is FrameworkElement focusInvokerElement)) return; if (focusInvoker.ParentElement is null) return; if (focusInvokerElement.Parent is Panel actualParentPanel) actualParentPanel.Children.Remove(focusInvokerElement); else if (focusInvokerElement.Parent is Decorator actualParentDecorator) actualParentDecorator.Child = null; else return; if (focusInvoker.ParentElement is Panel parentPanel) { if (focusInvoker.ParentIndex != null) { parentPanel.Children.RemoveAt(focusInvoker.ParentIndex.Value); parentPanel.Children.Insert(focusInvoker.ParentIndex.Value, focusInvokerElement); } else { parentPanel.Children.Add(focusInvokerElement); } } else if (focusInvoker.ParentElement is Decorator parentDecorator) { parentDecorator.Child = focusInvokerElement; } } catch (Exception E) { LogException(E); } } private static void ReAllocate(this FrameworkElement focusInvokerElement) { try { var preFocusParent = GetPreFocusParent(focusInvokerElement); if (preFocusParent is null) return; if (focusInvokerElement.Parent is Panel actualParentPanel) actualParentPanel.Children.Remove(focusInvokerElement); else if (focusInvokerElement.Parent is Decorator actualParentDecorator) actualParentDecorator.Child = null; else return; if (preFocusParent is Panel parentPanel) { var preFocusChildIndex = GetPreFocusChildIndex(focusInvokerElement); if (preFocusChildIndex != null) { parentPanel.Children.RemoveAt(preFocusChildIndex.Value); parentPanel.Children.Insert(preFocusChildIndex.Value, focusInvokerElement); } else { parentPanel.Children.Add(focusInvokerElement); } } else if (preFocusParent is Decorator parentDecorator) { parentDecorator.Child = focusInvokerElement; } } catch (Exception E) { LogException(E); } } public static void InvokeGotFocus(object sender, EventArgs e) { try { if (sender is FrameworkElement senderElement) { SetPreFocusParent(senderElement, senderElement.Parent); if (senderElement.Parent is Panel actualParentPanel) SetPreFocusChildIndex(senderElement, actualParentPanel.Children.IndexOf(senderElement)); } GotFocus?.Invoke(sender, e); } catch (Exception E) { LogException(E); } } public static void InvokeLostFocus(object sender, EventArgs e) { LostFocus?.Invoke(sender, e); if (sender is IFocusInvoker focusSender) focusSender.ReAllocate(); else if (sender is FrameworkElement senderElement) senderElement.ReAllocate(); } #region Attached Properties #region PreFocusChildIndex private static int? GetPreFocusChildIndex(DependencyObject obj) { return (int?)obj.GetValue(PreFocusChildIndexProperty); } private static void SetPreFocusChildIndex(DependencyObject obj, int? value) { obj.SetValue(PreFocusChildIndexProperty, value); } public static readonly DependencyProperty PreFocusChildIndexProperty = DependencyProperty.RegisterAttached("PreFocusChildIndex", typeof(int?), typeof(UIElement), new PropertyMetadata(null)); #endregion #region PreFocusParent private static DependencyObject GetPreFocusParent(DependencyObject obj) { return (DependencyObject)obj.GetValue(PreFocusParentProperty); } private static void SetPreFocusParent(DependencyObject obj, DependencyObject value) { obj.SetValue(PreFocusParentProperty, value); } public static readonly DependencyProperty PreFocusParentProperty = DependencyProperty.RegisterAttached("PreFocusParent", typeof(DependencyObject), typeof(UIElement), new PropertyMetadata(null)); #endregion #endregion } }