当前位置:  开发笔记 > 编程语言 > 正文

WPF用户控制父级

如何解决《WPF用户控制父级》经验,为你挑选了8个好方法。

我有一个用户控件,我MainWindow在运行时加载.我无法从包含窗口获取句柄UserControl.

我试过了this.Parent,但它总是空的.有谁知道如何从WPF中的用户控件获取包含窗口的句柄?

以下是控件的加载方式:

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

Ian Oakes.. 341

尝试使用以下内容

Window parentWindow = Window.GetWindow(userControlReference);

GetWindow方法将为您移动VisualTree并找到托管您控件的窗口.

您应该在加载控件后运行此代码,以防止GetWindow方法返回null.EG发布一个事件:

this.Loaded += new RoutedEventHandler(UserControl_Loaded); 

我发现它返回null的原因.我将此代码放入我的用户控件的构造函数中.您应该在加载控件后运行此代码.EG连接一个事件:this.Loaded + = new RoutedEventHandler(UserControl_Loaded); (105认同)

仍然返回null.这就像控件没有父级一样. (6认同)

我使用上面的代码并获取parentWindow也为我返回null. (2认同)


小智.. 33

我会加上我的经验.虽然使用Loaded事件可以完成这项工作,但我认为覆盖OnInitialized方法可能更合适.首次显示窗口后出现加载.OnInitialized使您有机会进行任何更改,例如,在窗口呈现之前向窗口添加控件.



1> Ian Oakes..:

尝试使用以下内容

Window parentWindow = Window.GetWindow(userControlReference);

GetWindow方法将为您移动VisualTree并找到托管您控件的窗口.

您应该在加载控件后运行此代码,以防止GetWindow方法返回null.EG发布一个事件:

this.Loaded += new RoutedEventHandler(UserControl_Loaded); 


我发现它返回null的原因.我将此代码放入我的用户控件的构造函数中.您应该在加载控件后运行此代码.EG连接一个事件:this.Loaded + = new RoutedEventHandler(UserControl_Loaded);
仍然返回null.这就像控件没有父级一样.
我使用上面的代码并获取parentWindow也为我返回null.

2> 小智..:

我会加上我的经验.虽然使用Loaded事件可以完成这项工作,但我认为覆盖OnInitialized方法可能更合适.首次显示窗口后出现加载.OnInitialized使您有机会进行任何更改,例如,在窗口呈现之前向窗口添加控件.


+1表示正确.了解使用哪种技术有时会很微妙,特别是当你有混合事件和覆盖(加载事件,OnLoaded覆盖,初始化事件,OnInitialized覆盖,etcetcetc)时.在这种情况下,OnInitialized是有意义的,因为您要查找父级,并且必须初始化控件以使父级"存在".加载意味着不同的东西.
`Window.GetWindow`仍然在`OnInitialized`中返回`null`.似乎只在`Loaded`事件中工作.

3> Jobi Joy..:

尝试使用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);
        }
    }


我发现它返回null的原因.我将此代码放入我的用户控件的构造函数中.您应该在加载控件后运行此代码.EG连接一个事件:this.Loaded + = new RoutedEventHandler(UserControl_Loaded)

4> Alan Le..:

我需要在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);

    ...
}



5> 小智..:

这个怎么样:

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



6> Anthony Main..:

这种方法对我有用,但它不像你的问题那样具体:

App.Current.MainWindow



7> 小智..:

如果您发现此问题并且VisualTreeHelper不适合您或偶尔工作,您可能需要在算法中包含LogicalTreeHelper.

这是我正在使用的:

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



8> Alex..:

我发现UserControl的父级在构造函数中始终为null,但在任何事件处理程序中父级都是正确设置的.我想它必须与控件树的加载方式有关.因此,为了解决这个问题,您可以在控件Loaded事件中获取父级.

对于示例结帐,此问题WPF用户控件的DataContext为空

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有