Home > database >  Create dropdown element which opens and closes by button click
Create dropdown element which opens and closes by button click

Time:11-01

I want a button that can open and close area which contains clickable controls. Currently I try to implement this with popup. XAML:

<Window x:Class="PopupTrouble.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Height="200" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Content="Open popup" Click="Button_Click"/>
        <Popup x:Name="PopupInstance"
               AllowsTransparency="True"
               StaysOpen="False">
            <Border BorderThickness="1" BorderBrush="Black">
                <StackPanel>
                    <TextBlock Text="Some other clickable controls"/>
                    <RadioButton IsChecked="True" Content="Option one" GroupName="Group"></RadioButton>
                    <RadioButton IsChecked="False" Content="Option two" GroupName="Group"></RadioButton>
                </StackPanel>
            </Border>
        </Popup>
    </Grid>
</Window>

Code behind file:

using System.Windows;

namespace PopupTrouble
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e) => PopupInstance.IsOpen = !PopupInstance.IsOpen;
    }
}

The problem is when popup is open button reopens it instead of closing it. If I'm right, this happens because popup is losing focus when I click button. I can't just set StaysOpen property to true because in that way popup will remain during mouse scroll or mouse click on other controls.
Gif with current behavior (gifyu.com)

Is there any way to change this behavior and make WPF don't change focus when I click button?

I tried to implement this with FocusManager and check if new element which get focused is button, but get another problem - controls in popup don't work correctly.

CodePudding user response:

Perhaps this solution will suit you without using Code Behind.

    <Grid Height="200" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center">
            <ToggleButton x:Name="toggleButton"
                          IsChecked="False">
                <ToggleButton.Style>
                    <Style TargetType="ToggleButton">
                        <Setter Property="Content" Value="Open popup"/>
                        <Style.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Content" Value="Close popup"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </ToggleButton.Style>
            </ToggleButton>
        <Popup x:Name="PopupInstance"
                AllowsTransparency="True"
                IsOpen="{Binding IsChecked, ElementName=toggleButton, Mode=TwoWay}">
            <Border BorderThickness="1" BorderBrush="Black">
                <StackPanel>
                    <TextBlock Text="Some other clickable controls"/>
                    <RadioButton IsChecked="True" Content="Option one" GroupName="Group"></RadioButton>
                    <RadioButton IsChecked="False" Content="Option two" GroupName="Group"></RadioButton>
                </StackPanel>
            </Border>
        </Popup>
    </Grid>

popup doesn't close when I scroll mouse or click outside popup or button.

It is possible to make the Popup close when the button loses focus:

            <Popup x:Name="PopupInstance"
                   AllowsTransparency="True"
                   IsOpen="{Binding IsChecked, ElementName=toggleButton, Mode=TwoWay}"
                   StaysOpen="{Binding IsFocused, ElementName=toggleButton}">

Or yet this variant:

    <Popup x:Name="PopupInstance"
            AllowsTransparency="True"
            IsOpen="{Binding IsChecked, ElementName=toggleButton, Mode=TwoWay}"
            StaysOpen="{Binding IsMouseOver, ElementName=toggleButton}">
  • Related