Как закрыть ChildWindow от кнопки UserControl, загруженной в него? - PullRequest
2 голосов
/ 26 ноября 2009

это мой код ChildWindow xaml:

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>

Это мой код UserControl1 xaml:

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

Это мой UserControl C #:

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

Попытка этого способа не работает. Любая идея?

Tks Josi

Ответы [ 2 ]

4 голосов
/ 26 ноября 2009

Проблема родителя UserControl не в ChildWindow, а в сетке внутри дочернего окна. Вам необходимо получить родительский элемент родительского элемента UserControl, чтобы перейти к ChildWindow: -

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

Несмотря на то, что встраивание этого в ваш UserControl будет плохой практикой, вы будете указывать потребителю вашего UserControl, где его можно разместить. В приведенном выше случае, чтобы пользовательский элемент управления работал, он всегда должен быть прямым потомком корня макета.

Лучшим подходом было бы поискать в визуальном дереве, зацикливаясь на ChildWindow. Я бы использовал этот вспомогательный метод (на самом деле я бы поместил его в статический класс вспомогательных расширений, но здесь все будет просто).

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

Теперь вы можете использовать методы LINQ для получения ChildWindow с: -

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

Это найдет первого предка вашего UserControl, который оказался ChildWindow. Это позволяет разместить UserControl на любой глубине в дочерних окнах XAML, он все равно найдет правильный объект.

0 голосов
/ 15 июля 2010

Вот мое текущее (временное) решение - статический класс ChildPopupWindowHelper для открытия всплывающих окон без необходимости создания глупого экземпляра ChildWindow XAML для каждого пользовательского элемента управления, который я хочу предоставить.

  • Создайте пользовательский контроль как обычно, наследуя от ChildWindowUserControl

  • Затем откройте всплывающее окно с помощью

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

Я не совсем доволен этим и приветствую улучшения этого паттерна.


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