WPF Checkbox Combobox direct click on button after selection

Asked

Viewed 331 times

0

I have some comboxboxes I fill with checkboxes. After selecting the items click on search, but the first click is used to compress the combo and then click again to trigger the button.

Is there any way to avoid having to double-click a button after opening a combobox? Make the first click compress the combo and press the button.

As it is: I click on the combobox, select the items, click off the combo, click on the button. (Obs. even clicking on the button, the first click is always to compress the combo).

As it would be: I click on the combobox, select the items, click on the button.

<ComboBox 
    Grid.Column="3" 
    Grid.Row="1"
    x:Name="cmbGrupo" 
    IsEditable="True"
    IsReadOnly="False"                     
    Width="120" 
    SelectedIndex="0" 
    >
    <ComboBox.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="DarkGray"/>
    </ComboBox.Resources>

    <ComboBox.ItemTemplate>
        <DataTemplate>
            <CheckBox 
                x:Name="chkGrupo" 
                Content="{Binding Content}" 
                IsChecked="{Binding IsChecked}" 
                IsEnabled="{Binding IsEnabled}" 
                Checked="chk_Changed" 
                Unchecked="chk_Changed"
                />

        </DataTemplate>
    </ComboBox.ItemTemplate>
    <ComboBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ComboBox.ItemsPanel>
</ComboBox>

<Button 
    x:Name="btnPesquisar" 
    Content="Pesquisar" 
    Grid.Column="17"
    Grid.Row="1"
    Width="130" 
    Click="btnPesquisar_Click"
    />
  • No code makes it hard to help you. Add combobox and button code.

  • Done @Stanleyipc

1 answer

1


First, what happens is that Combobox has been implemented so that when Dropdown is open it captures the mouse. This is native to Combobox and means that:

Of Capture and Uncapture the mouse:

When an object captures the mouse, all autonomous system related mouse events are treated autonomous system if the object with the mouse capture run the event, even if the mouse pointer is over another object.

So that’s what your problem is.

Now about:

Is there any way to avoid having to double-click a button after opening a combobox? Make the first click compress the combo and press the button.

As far as I know, there are two ways and several variations of them. I’ll put the two ways.

First method:

   private void Win_Loaded(object sender, RoutedEventArgs e)
    {
        cmbGrupo.ItemsSource = typeof(Colors).GetProperties();
        Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(cmbGrupo, OutsideControlClick);
    }

    public void OutsideControlClick(object sender, MouseButtonEventArgs e)
    {
        cmbGrupo.ReleaseMouseCapture();
    }
  • Loading the window will add the "Addpreviewmousedownoutsidecaptured" event to your Combobox. This means an event is running when some mouse button is pressed outside the element that is capturing mouse events (reference).
  • The event is only activated when you click inside the Window. The "Close" and "Minimize" buttons Window, will not activate the event.

Second Method:

private void ComboBox_DropDownClosed(object sender, EventArgs e)
    {
        Point m = Mouse.GetPosition(this);
        VisualTreeHelper.HitTest(this, this.FilterCallback, this.ResultCallback, new PointHitTestParameters(m));
    }

    private HitTestFilterBehavior FilterCallback(DependencyObject obj)
    {
        Control control = obj as Control;
        if(control == null) return HitTestFilterBehavior.Continue;
        if(control is Window) return HitTestFilterBehavior.Continue;
        if(control is ComboBox) return HitTestFilterBehavior.Stop; 

        if (control.Focusable)
        {
            MouseDevice mouseDevice = Mouse.PrimaryDevice;
            MouseButtonEventArgs mouseButtonEventArgs = new MouseButtonEventArgs(mouseDevice, 0, MouseButton.Left)
            {
                RoutedEvent = Mouse.MouseDownEvent,
                Source = control
            };
            control.RaiseEvent(mouseButtonEventArgs);
            return HitTestFilterBehavior.Stop;
        }
        return HitTestFilterBehavior.Continue;
    }

    private HitTestResultBehavior ResultCallback(HitTestResult r)
    {
        return HitTestResultBehavior.Continue;
    }
  • When closing the DropDonw it will focus the control where the pointer is positioned before performing another action with the mouse.

In your case I would put some of these methods in a DepedencyProperty for reuse. If you do this, share it with us ;D

I hope I helped. Hugs

  • I used the first option, it worked perfectly! Thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.