views:

447

answers:

2

Hi, this is my ChildWindow xaml code:

1    <Grid x:Name="LayoutRoot">
2       <Grid x:Name="teste">
3       <Grid.ColumnDefinitions>
4        <ColumnDefinition Width="*"/>
5        <ColumnDefinition Width="*"/>
6       </Grid.ColumnDefinitions>
7       <Grid.RowDefinitions>
8        <RowDefinition />
9        <RowDefinition Height="Auto" />
10      </Grid.RowDefinitions>
11      <local:UserControl1 Grid.Row="0" Grid.ColumnSpan="2"/>
12     </Grid>
13   </Grid>

This is my UserControl1 xaml code:

1     <Grid x:Name="LayoutRoot" Background="#FFA34444">
2      <Button Click="Child_Close" Content="Cancel">
3     </Grid>

This is my UserControl C#:

private void Child_Close(object sender, System.Windows.RoutedEventArgs e)
{
 ChildWindow cw = (ChildWindow)this.Parent;
 cw.Close();
}

Trying this way doesn't work. Any Idea?

Tks Josi

+1  A: 

The problem the UserControl's parent is not the ChildWindow, its the Grid inside the child window. You need to get the parent of the parent of the UserControl to navigate to the ChildWindow:-

ChildWindow cw = (ChildWindow)((FrameworkElement)this.Parent).Parent;

However embedding this in your UserControl would bad practice, you would be stipulating to the consumer of your UserControl where the it can be sited. In the above case for the user control to work it would need to always be a direct child of the Layout root.

A better approach would be to search up the visual tree looing for a ChildWindow. I would use this helper method (actually I'd place this in a helper extensions static class but I'll keep it simple here).

private IEnumerable<DependencyObject> Ancestors()
{
 DependencyObject current = VisualTreeHelper.GetParent(this);
 while (current != null)
 {
  yield return current;
  current = VisualTreeHelper.GetParent(current);
 }
}

Now you can use LINQ methods to get the ChildWindow with:-

ChildWindow cw = Ancestors().OfType<ChildWindow>().FirstOrDefault();

This will find the first ancestor of your UserControl that happens to be ChildWindow. This allows your UserControl to be placed at any depth in the child windows XAML, it would still find the correct object.

AnthonyWJones
A: 

Here's my current (temporary) solution - a ChildPopupWindowHelper static class to open popup windows without having to create a stupid ChildWindow XAML instance for every usercontrol I want to expose.

  • Create usercontrol as usual, inheriting from ChildWindowUserControl

  • Then open a popup with

    ChildPopupWindowHelper.ShowChildWindow("TITLE", new EditFooControl())

I'm not completely happy with this and welcome enhancements to this pattern.


public static class ChildPopupWindowHelper
{
    public static void ShowChildWindow(string title, ChildWindowUserControl userControl)
    {
        ChildWindow cw = new ChildWindow()
        {
            Title = title
        };
        cw.Content = userControl;
        cw.Show();
    }
}

public class ChildWindowUserControl : UserControl
{
    public void ClosePopup()
    {
        DependencyObject current = this;
        while (current != null)
        {
            if (current is ChildWindow)
            {
                (current as ChildWindow).Close();
            }

            current = VisualTreeHelper.GetParent(current);
        }
    }
}
Simon_Weaver