[C#] WPF 사용자 컨트롤 부모

MainWindow런타임에 로드하는 사용자 정의 컨트롤이 있습니다. 에서 포함 창에 대한 핸들을 얻을 수 없습니다 UserControl.

시도 this.Parent했지만 항상 null입니다. 누구나 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);
}



답변

다음을 사용해보십시오.

Window parentWindow = Window.GetWindow(userControlReference);

GetWindow메서드는 VisualTree를 안내하고 컨트롤을 호스팅하는 창을 찾습니다.

GetWindow메서드가 반환 되지 않도록하려면 컨트롤이로드 된 후 (창 생성자가 아닌)이 코드를 실행해야합니다 null. 예를 들어 이벤트를 연결하십시오.

this.Loaded += new RoutedEventHandler(UserControl_Loaded); 


답변

내 경험을 추가하겠습니다. Loaded 이벤트를 사용하면 작업을 수행 할 수 있지만 OnInitialized 메서드를 재정의하는 것이 더 적합 할 수 있습니다. 창을 처음 표시 한 후로드가 발생합니다. OnInitialized를 사용하면 렌더링 전에 창에 컨트롤을 추가하는 등의 변경 작업을 수행 할 수 있습니다.


답변

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


답변

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

    ...
}


답변

이 방법은 저에게 효과적이지만 귀하의 질문만큼 구체적이지 않습니다.

App.Current.MainWindow


답변

이 질문을 찾았는데 VisualTreeHelper가 작동하지 않거나 산발적으로 작동하지 않는 경우 알고리즘에 LogicalTreeHelper를 포함시켜야합니다.

여기 내가 사용하는 것이 있습니다 :

public static T TryFindParent<T>(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<T>(parent);
}


답변

이건 어때요:

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