2014-06-30 21 views
5

Drugi dzień walki z tym problemem.Niewidoczne otwarte okienko wyskakujące

Aby odtworzyć, należy utworzyć nową aplikację WPF XAML

<StackPanel Orientation="Horizontal" VerticalAlignment="Top"> 
    <Button Width="100" Height="100" MouseMove="Button_MouseMove"/> 
    <Popup x:Name="popup" StaysOpen="False" AllowsTransparency="True" Placement="Center"> 
     <TextBlock>Some random text</TextBlock> 
    </Popup> 
    <CheckBox IsChecked="{Binding (Popup.IsOpen), ElementName=popup}">Popup</CheckBox> 
</StackPanel> 

i kod przycisku

private void Button_MouseMove(object sender, MouseEventArgs e) 
{ 
    popup.IsOpen = true; 
} 

ruchu kursora myszy, aby otworzyć okienko, kliknij w innym miejscu, aby zamknąć. Kliknij przycisk, aby mieć błąd: wyskakujące okienko to IsOpen == true (można je zobaczyć w polu wyboru lub z punktem przerwania w programie obsługi), gdy jest niewidoczne.

WTF?

I moim pierwotnym problemem jest, jak się wydaje, to, co ustawienie nie jest natychmiastowe. Aby przykład, gdy próbuję ustawić go false w MouseMove imprezy Popup „s, potem dostać MouseEnter i MouseMove wydarzenia Button opalane prawo podczas że

IsOpen = true; 

samo z ustawieniem go true istnieją 2 (!) MouseMove zdarzenia występuje, umieścić tę linię do obsługi zdarzeń, aby zobaczyć to

System.Diagnostics.Trace.WriteLine("M"); 

Nie będzie 2 M w Output oknie VS, natomiast Popup (gdy StayOpen=false) zakłada, że ​​przechwytuje zdarzenia myszy i robi to, ale nie od razu.

Czy ktoś może mi wyjaśnić, co się dzieje? Nie chcę żadnych zdarzeń podczas (lub krótko po? Jak sprawdzić, czy to prawda?) Ustawienie IsOpen. Próbowaliśmy już dziesiątki rzeczy: Dispatcher.InvokeAsync, zmienne, liczniki, itp

+0

możliwe duplikat [WPF Popup traci ostrość, ale pozostaje otwarty] (http://stackoverflow.com/questions/14404897/wpf-popup-loses-focus-but-stays-opened). Zobacz odpowiedź tam: najprawdopodobniej powiązanie z IsOpen powoduje, że właściwość StaysOpen nie działa poprawnie ... – qqbenq

+0

@qqbenq, nie ma nic wspólnego z fokusem. Wiązanie tutaj polega jedynie na zademonstrowaniu problemu (usunięcie go i użycie breakpoint = tego samego problemu). – Sinatr

+0

'Okno podręczne nie otwiera się automatycznie, gdy wskaźnik myszy przesunie się nad obiektem nadrzędnym. Jeśli chcesz, aby okno podręczne było automatycznie otwierane, użyj etykiety ToolTip lub ToolTipService. Aby uzyskać więcej informacji, zobacz Omówienie ToolTip "wzięte z [tutaj] (http://msdn.microsoft.com/en-us/library/ms749018 (v = vs.110) .aspx) – Kcvin

Odpowiedz

4

Myślę, że masz rację z asynchronicznym założeniem. Podczas utraty ostrości wartość IsOpen jest ustawiona na wartość false, ale przycisk MouseMove wyzwala ponowne ustawienie. Jakaś dziwna magia wewnątrz łamie kod.

2 możliwe rozwiązania znalazłem, w zależności od potrzeb:

  1. jawnie ustawić IsOpen do false po popup zamknięte (bash asynchroniczny)
  2. # 1 + Wyłączenie przycisku podczas popup IsOpen == true

Pierwsze podejście spowoduje ukrycie okna popup podczas klikania przycisku. Drugie podejście przyjdzie wraz z lekkim migotania - przy szybkim naciśnięciu przycisku - ale utrzymuje okienko otwarte:

dla pierwszego podejścia, należy wykonać następujące procedury obsługi zdarzeń (może nie sprawdzić właściwość pierwszy):

private void Button_MouseMove(object sender, MouseEventArgs e) 
{ 
    popup.IsOpen = true; 
} 

private void Popup_OnClosed(object sender, EventArgs e) 
{ 
    if (popup.IsOpen) 
     popup.IsOpen = false; 
} 

na drugim podejściu, użyj BoolInvertConverter i wiązać je jeden sposób, aby popup:

IsEnabled="{Binding (Popup.IsOpen), ElementName=popup, Converter={StaticResource BoolInvertConverter}, Mode=OneWay}" 
+0

Wydaje się, że działa miło, biorąc pod uwagę okoliczności. Kudos =) – icebat

+0

'Zamknięty' i ustawienie' IsOpen = false' to oszustwo, ale działa idealnie, dzięki! Już rozwiązałem problem za pomocą kliknięcia, wyświetlając "Popup" na górze tego przycisku (z tym samym przyciskiem co jeden poniżej), więc nie można * kliknąć * it = P – Sinatr

+0

@Sinatr Tak, to znacznie więcej obejść/oszukać, zamiast naprawić. Jeśli chcesz to naprawić, przejdź do Microsoftu i sprawdź w swoim kodzie! :) – Herdo

2

dobrze, MouseMove i MouseEnter nazywane są zarówno po naciśnięciu przycisku (nawet jeśli klawiszem Spacja), więc prowadzi to do sytuacji, gdy Popup próbuje zamknąć przy jednoczesnym ustawieniu wartości IsOpen na wartość true w tym samym czasie. Prostym rozwiązaniem może być podzielenie tych dwóch zdarzeń.

Jednym ze sposobów może być przyklejenie się do MouseEnter i otwarcie Popup tylko raz, po najechaniu na daną Button. Podobnie jak w przykładzie:

private Button currentPopupHolder; 
private void Button_MouseEnter(object sender, MouseEventArgs e) 
{ 
    var btn = sender as Button; 
    if (currentPopupHolder != btn) 
    { 
     popup.IsOpen = true; 
     currentPopupHolder = btn; 
    } 
} 

private void Button_MouseLeave(object sender, MouseEventArgs e) 
{ 
    currentPopupHolder = null; 
} 

Chociaż sama Button generuje Popup nie należy otwierać więcej niż raz tego wydarzenia (w tym momencie, gdy zostanie naciśnięty przycisk).

+0

Pomysł jest dobry, ale wyraźne 'IsOpen = true' w rozwiązaniu' OnClosed' z @Herdo jest lepsze. – Sinatr

Powiązane problemy