C# WPF 用户控件父级
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/302839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF User Control Parent
提问by donniefitz2
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
.
我有一个MainWindow
在运行时加载到 a中的用户控件。我无法从UserControl
.
I have tried this.Parent
, but it's always null. Does anyone know how to get a handle to the containing window from a user control in WPF?
我试过this.Parent
,但它总是为空。有谁知道如何从 WPF 中的用户控件获取包含窗口的句柄?
Here is how the control is loaded:
下面是控件的加载方式:
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);
}
回答by Jobi Joy
Try using VisualTreeHelper.GetParent or use the bellow recursive function to find the parent window.
尝试使用 VisualTreeHelper.GetParent 或使用波纹管递归函数来查找父窗口。
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);
}
}
回答by Ian Oakes
Try using the following:
尝试使用以下方法:
Window parentWindow = Window.GetWindow(userControlReference);
The GetWindow
method will walk the VisualTree for you and locate the window that is hosting your control.
该GetWindow
方法将为您遍历 VisualTree 并找到承载您的控件的窗口。
You should run this code after the control has loaded (and not in the Window constructor) to prevent the GetWindow
method from returning null
. E.g. wire up an event:
您应该在控件加载后(而不是在 Window 构造函数中)运行此代码,以防止该GetWindow
方法返回null
. 例如连接一个事件:
this.Loaded += new RoutedEventHandler(UserControl_Loaded);
回答by Alex
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.
我发现 UserControl 的父级在构造函数中始终为空,但在任何事件处理程序中,父级都设置正确。我想它一定与控制树的加载方式有关。因此,要解决此问题,您只需在控件 Loaded 事件中获取父级即可。
For an example checkout this question WPF User Control's DataContext is Null
回答by Alan Le
I needed to use the Window.GetWindow(this) method within Loaded event handler. In other words, I used both Ian Oakes' answer in combination with Alex's answer to get a user control's parent.
我需要在 Loaded 事件处理程序中使用 Window.GetWindow(this) 方法。换句话说,我将 Ian Oakes 的答案与 Alex 的答案结合使用,以获取用户控件的父级。
public MainView()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainView_Loaded);
}
void MainView_Loaded(object sender, RoutedEventArgs e)
{
Window parentWindow = Window.GetWindow(this);
...
}
回答by paul
I'll add my experience. Although using the Loaded event can do the job, I think it may be more suitable to override the OnInitialized method. Loaded occurs after the window is first displayed. OnInitialized gives you chance to make any changes, for example, add controls to the window before it is rendered.
我来补充一下我的经验。虽然使用 Loaded 事件可以完成这项工作,但我认为重写 OnInitialized 方法可能更合适。Loaded 发生在窗口第一次显示之后。OnInitialized 使您有机会进行任何更改,例如,在呈现窗口之前向窗口添加控件。
回答by Eric Coulson
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));
}
}
}
回答by Eric Coulson
DependencyObject parent = ExVisualTreeHelper.FindVisualParent<UserControl>(this);
回答by Anthony Main
This approach worked for me but it is not as specific as your question:
这种方法对我有用,但不像你的问题那么具体:
App.Current.MainWindow
回答by Agus Syahputra
DependencyObject GetTopParent(DependencyObject current)
{
while (VisualTreeHelper.GetParent(current) != null)
{
current = VisualTreeHelper.GetParent(current);
}
return current;
}
DependencyObject parent = GetTopParent(thisUserControl);
回答by Pnct
Another way:
其它的办法:
var main = App.Current.MainWindow as MainWindow;