WPF User Control Parent

后端 未结 17 1001
不知归路
不知归路 2020-11-28 02:18

I have a user control that I load into a MainWindow at runtime. I cannot get a handle on the containing window from the UserControl.

I hav

相关标签:
17条回答
  • 2020-11-28 02:33

    I've found that the parent of a UserControl is always null in the constructor, but in any event handlers the parent is set correctly. I guess it must have something to do with the way the control tree is loaded. So to get around this you can just get the parent in the controls Loaded event.

    For an example checkout this question WPF User Control's DataContext is Null

    0 讨论(0)
  • 2020-11-28 02:36

    Use VisualTreeHelper.GetParent or the recursive function below to find the parent window.

    public static Window FindParentWindow(DependencyObject child)
    {
        DependencyObject parent= VisualTreeHelper.GetParent(child);
    
        //CHeck if this is the end of the tree
        if (parent == null) return null;
    
        Window parentWindow = parent as Window;
        if (parentWindow != null)
        {
            return parentWindow;
        }
        else
        {
            //use recursion until it reaches a Window
            return FindParentWindow(parent);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 02:36

    This approach worked for me but it is not as specific as your question:

    App.Current.MainWindow
    
    0 讨论(0)
  • 2020-11-28 02:36

    Gold plated edition of the above (I need a generic function which can infer a Window within the context of a MarkupExtension:-

    public sealed class MyExtension : MarkupExtension
    {
        public override object ProvideValue(IServiceProvider serviceProvider) =>
            new MyWrapper(ResolveRootObject(serviceProvider));
        object ResolveRootObject(IServiceProvider serviceProvider) => 
             GetService<IRootObjectProvider>(serviceProvider).RootObject;
    }
    
    class MyWrapper
    {
        object _rootObject;
    
        Window OwnerWindow() => WindowFromRootObject(_rootObject);
    
        static Window WindowFromRootObject(object root) =>
            (root as Window) ?? VisualParent<Window>((DependencyObject)root);
        static T VisualParent<T>(DependencyObject node) where T : class
        {
            if (node == null)
                throw new InvalidOperationException("Could not locate a parent " + typeof(T).Name);
            var target = node as T;
            if (target != null)
                return target;
            return VisualParent<T>(VisualTreeHelper.GetParent(node));
        }
    }
    

    MyWrapper.Owner() will correctly infer a Window on the following basis:

    • the root Window by walking the visual tree (if used in the context of a UserControl)
    • the window within which it is used (if it is used in the context of a Window's markup)
    0 讨论(0)
  • 2020-11-28 02:36

    The Window.GetWindow(userControl) will return the actual window only after the window was initialized (InitializeComponent() method finished).

    This means, that if your user control is initialized together with its window (for instance you put your user control into the window's xaml file), then on the user control's OnInitialized event you will not get the window (it will be null), cause in that case the user control's OnInitialized event fires before the window is initialized.

    This also means that if your user control is initialized after its window, then you can get the window already in the user control's constructor.

    0 讨论(0)
  • 2020-11-28 02:39

    How about this:

    DependencyObject parent = ExVisualTreeHelper.FindVisualParent<UserControl>(this);
    
    public static class ExVisualTreeHelper
    {
        /// <summary>
        /// Finds the visual parent.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender">The sender.</param>
        /// <returns></returns>
        public static T FindVisualParent<T>(DependencyObject sender) where T : DependencyObject
        {
            if (sender == null)
            {
                return (null);
            }
            else if (VisualTreeHelper.GetParent(sender) is T)
            {
                return (VisualTreeHelper.GetParent(sender) as T);
            }
            else
            {
                DependencyObject parent = VisualTreeHelper.GetParent(sender);
                return (FindVisualParent<T>(parent));
            }
        } 
    }
    
    0 讨论(0)
提交回复
热议问题