2010-10-28 3 views
0

Я довольно долго боролся с этим, и я не могу найти подходящее решение. Это сценарий снят. Представьте, у вас есть следующий код XAML:Закрытие всплывающего окна, когда его родитель обрушивается

<Grid x:Name="LayoutRoot" Background="White"> 
    <Grid x:Name="Host" Width="200" Height="200"> 
     <Popup IsOpen="True"> 
      <Button Content="Some Button" Click="Button_Click" /> 
     </Popup> 
    </Grid> 
</Grid> 

В обработчике событий Button_Click я все это разрушится сетки с именем хоста .

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    this.Host.Visibility = System.Windows.Visibility.Collapsed; 
} 

То, что я ожидал, было то, что всплывающее окно закрыло бы, спрятав кнопку. Я понимаю, что всплывающие окна не совпадают с VisualTree, и я понимаю, почему это может не работать так, как я ожидаю, но должен быть какой-то механизм для этого, чтобы это произошло автоматически. Единственное обходное решение, которое приходит мне на ум, - это LayoutUpdated, чтобы пересечь визуальное дерево и спросить родителя каждой кнопки, если он виден, и если я встречаю свернутый родительский элемент -> закрыть всплывающее окно. Однако представьте себе, что удар производительности имеет ОГРОМНОЕ визуальное дерево. Это безумие, чтобы пересечь визуальное дерево на каждом макете. Я открыт для любых предложений.

EDIT: Кажется, что я не полностью объяснил свой сценарий. Дело в том, чтобы свернуть всплывающее окно, если ЛЮБОЙ его родителя получает рушится (а не только сразу). В WPF есть полезное свойство: IsVisible, который отличается от Visibility. Например, Видимость еще может быть Visible, но IsVisible будет в этом случае ложным.

С наилучшими пожеланиями, K

ответ

-1

Если вы просто хотите, чтобы закрыть всплывающее окно, почему вы не установите IsOpen на всплывающей ЛОЖЬ.

<Grid x:Name="LayoutRoot" Background="White"> 
    <Grid x:Name="Host" Width="200" Height="200"> 
     <Popup x:Name="HostPopup" IsOpen="True"> 
      <Button Content="Some Button" Click="Button_Click" /> 
     </Popup> 
    </Grid> 
</Grid> 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    this.HostPopup.IsOpen = false; 
} 

Это закрывает всплывающее окно.

+0

Моя основная цель - закрыть всплывающее окно, когда любой из его родителей рухнет. –

+0

Хорошо, ладно, тогда мой ответ не то, что вам нужно. Насколько велико визуальное дерево (сколько пользовательских элементов управления «обертывает» всплывающее окно)? Вы добавили бы какой-то слушатель к каждому элементу обертывания, и если видимость изменится, вы можете выбросить событие или перейти в состояние ... Возможно, вы могли бы что-то сделать с поведением или состояниями ... – TerenceJackson

0

Я думаю, что вы нашли ошибку, или, по крайней мере, «странности» в элементе управления всплывающей - проверить это:

Моя первоначальная мысль была просто Bind видимость всплывающего окна к хосту. Это СЛЕДУЕТ работать.

<Grid x:Name="LayoutRoot" Background="White"> 
    <Grid x:Name="Host" Width="200" Height="200" Background="Aqua"> 
     <Popup IsOpen="True" Visibility="{Binding ElementName=Host, Path=Visibility}" Height="100" Width="100"> 
      <Button Content="Some Button" Click="Button_Click"/> 
     </Popup> 
    </Grid> 
</Grid> 

Но это не сработает. Сетка «Хост» исчезает, но я все еще вижу кнопку. Это смутило меня, поэтому я запустил Silverlight Spy и проверил это - настройка видимости всплывающего окна НЕ скрывает кнопку!

See Demo Video

Во всяком случае, для того, чтобы сделать эту работу, вам просто нужно массировать вещи немного, чтобы связать хост видимость свойству IsOpen. Я использовал конвертер здесь:

<UserControl.Resources> 
    <Junk:VisibilityToBoolConverter x:Key="VisibilityToBoolConverter"/> 
</UserControl.Resources> 
    <Grid x:Name="LayoutRoot" Background="White"> 
    <Grid x:Name="Host" Width="200" Height="200" Background="Aqua"> 
     <Popup IsOpen="{Binding ElementName=Host, Path=Visibility, Converter={StaticResource VisibilityToBoolConverter}}" Height="100" Width="100"> 
      <Button Content="Some Button" Click="Button_Click"/> 
     </Popup> 
    </Grid> 
</Grid> 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    this.Host.Visibility = System.Windows.Visibility.Collapsed; 

} 


public class VisibilityToBoolConverter : IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return ((Visibility) value) == Visibility.Visible; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Это работает на меня.

+0

Спасибо за ответ. Фактически, это будет работать только в случае, когда я разрушаю Host. Однако, если хост имеет самого родителя, и я разрушаю родительский хост, ничего не произойдет. Вся проблема в том, что я не знаю, какой родительский элемент PopUp будет свернут. –

+0

Я не думаю, что вы можете, по крайней мере, не так, как хотите. Он должен «работать» таким образом, но, как вы видели в видео, даже настройка видимости самого всплывающего окна на Collapsed не скрывает содержимое Popup. Я также попытался привязать IsOpen к видимости элемента управления Popup, но я узнал, что установка свойства Parent элемента управления Collapsed не сворачивает дочерние элементы управления - не уверен, как это работает честно. Я думаю, что единственный способ сделать эту работу - пока - знать, что такое родительский элемент управления, и связать его. –

Смежные вопросы