shahar eldad
shahar eldad

Reputation: 862

WPF popup doesn`t close on click

Update: Here is a link for a reproduction https://drive.google.com/file/d/0BzalDCHAtuAPUk5vWF9PVUE2QzQ/view?usp=sharing

Back to original question:

I tried to find some answer here but haven`t found any.

I have a collection of items where on click of an item a popup is opened, and when clicked outside of the item the popup is closed. From some reason, when the popup is opened, when I click the same item again the popup is closed and reopened instead of staying closed. Here are my pieces of code:

Some clarification: I have two collections. One is sitting inside an ItemsControl and one is sitting inside a ListView. The MouseClickToCommandBehavior below sits on both the ItemsControl and the ListView. I use it to tell the Popup when to open and close. I also need the popup to close when I click outside of the item. Currently when I click an item inside the ListView or the ItemsControl (when the popup for that item is already opened) the Popup reopens instead of closing. This occurs because of the StaysOpen property set to "false" which is required for the popup to close when I click outside of the item.

Back to original question:

The popup

<Popup IsOpen="{Binding ShowCustomerCardOptionsPopup, UpdateSourceTrigger=PropertyChanged}" StaysOpen="False"
       PlacementTarget="{Binding ElementName=CUstomerCardGrid}"
       Placement="Right">

The behavior to open the popup (which is set on the ListView)

<i:Interaction.Behaviors>
    <behaviors:MouseClickToCommandBehavior Command="{Binding OpenPopupForCustomerCard}" CommandParameter="{Binding ElementName=CustomerCardsListView, Path=SelectedItem}"/>
</i:Interaction.Behaviors>

The command action

private void OpenPopupForCustomerCardAction(ICustomerModel model)
{
    model.ShowCustomerCardOptionsPopup = !model.ShowCustomerCardOptionsPopup;
}

And the call stack when clicking on the same item

value: True
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at POS.Models.CustomerModel.set_ShowCustomerCardOptionsPopup(Boolean value)
at POS.ViewModels.CustomerViewModel.OpenPopupForCustomerCardAction(ICustomerModel model)
at POS.InfraStructure.ActionCommand`1.Execute(Object parameter)
at POS.Views.Behaviors.MouseClickToCommandBehavior.AssociatedObject_MouseUp(Object sender, MouseButtonEventArgs e)

====================
value: False
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at POS.Models.CustomerModel.set_ShowCustomerCardOptionsPopup(Boolean value)

====================
value: False
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at POS.Models.CustomerModel.set_ShowCustomerCardOptionsPopup(Boolean value)

====================
value: True
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at POS.Models.CustomerModel.set_ShowCustomerCardOptionsPopup(Boolean value)
at POS.ViewModels.CustomerViewModel.OpenPopupForCustomerCardAction(ICustomerModel model)
at POS.InfraStructure.ActionCommand`1.Execute(Object parameter)
at POS.Views.Behaviors.MouseClickToCommandBehavior.AssociatedObject_MouseUp(Object sender, MouseButtonEventArgs e)

I would love to know why is the "false" value called twice and how can I prevent either the false or second true from occurring (more preferbly the false and still have the behavior of StaysOpen="False")

Thanks

Upvotes: 2

Views: 2455

Answers (1)

Heiner
Heiner

Reputation: 2056

I had the same problem by opening or closing the Popup with a Button.

I needed to to disable IsHitTestVisible on the open / close Button while the Popup is open.

IsHitTestVisible="{Binding IsOpen, ElementName=MyPopup, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}}"

Otherwise, the Popup closes as defined by StaysOpen="False" when clicking on the Button. And after that it is opened again as a result of the Button click.

With this simple converter (just for completeness):

public class InverseBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !((bool)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !((bool)value);
    }
}

Upvotes: 3

Related Questions