WPF User Control Parent

Tengo un control de usuario que cargo en MainWindow en tiempo de ejecución. No puedo obtener un control sobre la ventana que contiene el UserControl .

Lo he intentado. this.Parent , pero siempre es nulo. ¿Alguien sabe cómo manejar la ventana contenedora desde un control de usuario en WPF?

Aquí se muestra cómo se carga el control:

 private void XMLLogViewer_MenuItem_Click(object sender, RoutedEventArgs e) { MenuItem application = sender as MenuItem; string parameter = application.CommandParameter as string; string controlName = parameter; if (uxPanel.Children.Count == 0) { System.Runtime.Remoting.ObjectHandle instance = Activator.CreateInstance(Assembly.GetExecutingAssembly().FullName, controlName); UserControl control = instance.Unwrap() as UserControl; this.LoadControl(control); } } private void LoadControl(UserControl control) { if (uxPanel.Children.Count > 0) { foreach (UIElement ctrl in uxPanel.Children) { if (ctrl.GetType() != control.GetType()) { this.SetControl(control); } } } else { this.SetControl(control); } } private void SetControl(UserControl control) { control.Width = uxPanel.Width; control.Height = uxPanel.Height; uxPanel.Children.Add(control); } 

Intente usar lo siguiente

 Window parentWindow = Window.GetWindow(userControlRefernce); 

El método GetWindow recorrerá VisualTree por usted y ubicará la ventana que aloja su control.

Debería ejecutar este código después de que se haya cargado el control para evitar que el método GetWindow devuelva nulo. EG cablear un evento:

 this.Loaded += new RoutedEventHandler(UserControl_Loaded); 

Añadiré mi experiencia. Aunque el uso del evento Loaded puede hacer el trabajo, creo que puede ser más adecuado anular el método OnInitialized. Cargado ocurre después de que la ventana se muestra por primera vez. OnInitialized le da la oportunidad de realizar cualquier cambio, por ejemplo, agregar controles a la ventana antes de que se represente.

Pruebe usar VisualTreeHelper.GetParent o use la siguiente función recursiva para encontrar la ventana principal.

  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); } } 

Necesitaba usar el método Window.GetWindow (this) dentro del controlador de eventos Loaded. En otras palabras, utilicé la respuesta de Ian Oakes en combinación con la respuesta de Alex para obtener el control del usuario.

 public MainView() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainView_Loaded); } void MainView_Loaded(object sender, RoutedEventArgs e) { Window parentWindow = Window.GetWindow(this); ... } 

Este enfoque funcionó para mí, pero no es tan específico como tu pregunta:

 App.Current.MainWindow 

Qué tal esto:

 DependencyObject parent = ExVisualTreeHelper.FindVisualParent(this); public static class ExVisualTreeHelper { ///  /// Finds the visual parent. ///  ///  /// The sender. ///  public static T FindVisualParent(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(parent)); } } } 

Descubrí que el padre de un UserControl siempre es nulo en el constructor, pero en cualquier caso los controladores el padre está configurado correctamente. Supongo que debe tener algo que ver con la forma en que se carga el árbol de control. Para evitar esto, puede obtener al padre en el evento Controlado cargado.

Para ver un ejemplo, consulte esta pregunta . El DataContext del control de usuario de WPF es nulo.

Si encuentra esta pregunta y el VisualTreeHelper no funciona para usted o no trabaja de manera esporádica, es posible que deba incluir LogicalTreeHelper en su algoritmo.

Esto es lo que estoy usando:

 public static T TryFindParent(DependencyObject current) where T : class { DependencyObject parent = VisualTreeHelper.GetParent(current); if( parent == null ) parent = LogicalTreeHelper.GetParent(current); if( parent == null ) return null; if( parent is T ) return parent as T; else return TryFindParent(parent); } 

De otra manera:

 var main = App.Current.MainWindow as MainWindow; 

Me está funcionando:

 DependencyObject GetTopLevelControl(DependencyObject control) { DependencyObject tmp = control; DependencyObject parent = null; while((tmp = VisualTreeHelper.GetParent(tmp)) != null) { parent = tmp; } return parent; } 

Esto no funcionó para mí, ya que fue demasiado arriba en el árbol, y obtuve la ventana raíz absoluta para toda la aplicación:

 Window parentWindow = Window.GetWindow(userControlReference); 

Sin embargo, esto funcionó para obtener la ventana inmediata:

 DependencyObject parent = uiElement; int avoidInfiniteLoop = 0; while ((parent is Window)==false) { parent = VisualTreeHelper.GetParent(parent); avoidInfiniteLoop++; if (avoidInfiniteLoop == 1000) { // Something is wrong - we could not find the parent window. break; } } Window window = parent as Window; window.DragMove(); 
 DependencyObject parent = ExVisualTreeHelper.FindVisualParent(this); 
 DependencyObject GetTopParent(DependencyObject current) { while (VisualTreeHelper.GetParent(current) != null) { current = VisualTreeHelper.GetParent(current); } return current; } DependencyObject parent = GetTopParent(thisUserControl); 

Edición dorada de lo anterior (Necesito una función genérica que pueda inferir una Window dentro del contexto de una MarkupExtension de MarkupExtension : –

 public sealed class MyExtension : MarkupExtension { public override object ProvideValue(IServiceProvider serviceProvider) => new MyWrapper(ResolveRootObject(serviceProvider)); object ResolveRootObject(IServiceProvider serviceProvider) => GetService(serviceProvider).RootObject; } class MyWrapper { object _rootObject; Window OwnerWindow() => WindowFromRootObject(_rootObject); static Window WindowFromRootObject(object root) => (root as Window) ?? VisualParent((DependencyObject)root); static T VisualParent(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(VisualTreeHelper.GetParent(node)); } } 

MyWrapper.Owner() correctamente una ventana de la siguiente manera:

  • la Window raíz al recorrer el árbol visual (si se usa en el contexto de un UserControl )
  • la ventana dentro de la cual se usa (si se usa en el contexto del marcado de una Window )