using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; namespace ServerManagerTool.Common.Utils { public static class WindowUtils { public static void RemoveDefaultResourceDictionary(Window window, string defaultDictionary) { if (window == null) return; var dictToRemove = window.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary)); if (dictToRemove != null) { window.Resources.MergedDictionaries.Remove(dictToRemove); } } public static void RemoveDefaultResourceDictionary(UserControl control, string defaultDictionary) { if (control == null) return; var dictToRemove = control.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary)); if (dictToRemove != null) { control.Resources.MergedDictionaries.Remove(dictToRemove); } } /// /// Finds a parent of a given item on the visual tree. /// /// The type of the queried item. /// A direct or indirect child of the queried item. /// The first parent item that matches the submitted type parameter. If not matching item can be found, a null reference is being returned. public static T TryFindParent(DependencyObject child) where T : DependencyObject { //get parent item DependencyObject parentObject = GetParentObject(child); //we've reached the end of the tree if (parentObject == null) return null; //check if the parent matches the type we're looking for T parent = parentObject as T; if (parent != null) return parent; //use recursion to proceed with next level return TryFindParent(parentObject); } /// /// This method is an alternative to WPF's method, which also supports content elements. /// Do note, that for content element, this method falls back to the logical tree of the element. /// /// The item to be processed. /// The submitted item's parent, if available. Otherwise null. public static DependencyObject GetParentObject(DependencyObject child) { if (child == null) return null; var contentElement = child as ContentElement; if (contentElement != null) { var parent = ContentOperations.GetParent(contentElement); if (parent != null) return parent; var fce = contentElement as FrameworkContentElement; return fce?.Parent; } //if it's not a ContentElement, rely on VisualTreeHelper return VisualTreeHelper.GetParent(child); } /// /// Recursively processes a given dependency object and all its children, and updates sources of all objects that use a binding expression on a given property. /// /// The dependency object that marks a starting point. This could be a dialog window or a panel control that hosts bound controls. /// The properties to be updated if /// or one of its childs provide it along with a binding expression. public static void UpdateBindingSources(DependencyObject obj, params DependencyProperty[] properties) { foreach (var depProperty in properties) { //check whether the submitted object provides a bound property that matches the property parameters var be = BindingOperations.GetBindingExpression(obj, depProperty); be?.UpdateSource(); } int count = VisualTreeHelper.GetChildrenCount(obj); for (int i = 0; i < count; i++) { //process child items recursively var childObject = VisualTreeHelper.GetChild(obj, i); UpdateBindingSources(childObject, properties); } } /// /// Tries to locate a given item within the visual tree, starting with the dependency object at a given position. /// /// The type of the element to be found on the visual tree of the element at the given location. /// The main element which is used to perform hit testing. /// The position to be evaluated on the origin. public static T TryFindFromPoint(UIElement reference, Point point) where T : DependencyObject { var element = reference.InputHitTest(point) as DependencyObject; if (element == null) return null; if (element is T) return (T)element; return TryFindParent(element); } } }