I used the above Answer but it seems to have a little bug on it.
The problem asserts itself only when the Popup is expanded (and StaysOpen=false
).
Here is how you reproduce it:
- The user toggles the
ToggleButton
(which expands the Popup
)
- The user (accidentally) moves the mouse off the
ToggleButton
.
- The user goes to toggle the
ToggleButton
(to close the Popup
manually)
At this point, the Popup
collapses, and then immediately expands (the same symptoms as the original symptoms above).
Here is what is happening:
If you have StaysOpen
set to false
, the Popup
internally captures the mouse (so that it knows if the user has clicked elsewhere … so that it can collapse the Popup
).
However, what that does is causes us not to get the MouseEnter
above (and thus the necessary and needed StaysOpen=true
behavior for manually toggling the Popup
open and closed).
Therefore, when the user goes to toggle the Popup
closed manually (step 3 above), the captured mouse tells the Popup to collapse … however, then the ToggleButton
kicks in and re-toggles the Popup open.
Here is the solution:
You need to make the ToggleButton
not respond to the mouse when the Popup
is expanded. In this way, only the StaysOpen=false
, mouse capture functionality kicks in … and the Popup
collapses … and doesn’t expand again.
How do you do this? You need to bind the IsHitTestVisible
property of the ToggleButton
to the !IsOpen
property of the Popup
.
To get the !IsOpen (Inverted IsOpen
Value) you need to use a IValueConverter
.
Here is the resulting Code:
1. XAML
<ToggleButton
Name="TestButton"
Width="100"
Height="28"
IsHitTestVisible="{Binding ElementName=PresetPopup, Path=IsOpen, Mode=OneWay, Converter={StaticResource BoolInverterConverter1}}" />
2. C# Converter Code behind
public class BoolInverterConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool)
{
return !((bool)value);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}