How to get a combobox to appropriately set focus directly after the popup closes

后端 未结 2 1459
别跟我提以往
别跟我提以往 2020-12-11 18:34

When the user is selecting values from a combobox, if they choose a value, the \"SelectionChanged\" event fires and the new value is set and everything\'s fine. If, however,

2条回答
  •  自闭症患者
    2020-12-11 19:34

    There's a DropDownClosed event:

    private void comboBox_DropDownClosed(object sender, EventArgs e)
    {
        Point m = Control.MousePosition;
        Point p = this.PointToClient(m);
        Control c = this.GetChildAtPoint(p);
        c.Focus();
    }
    

    This will only set focus to whatever control they clicked on. If they click a TextBox, for instance, the caret will be at the left rather than where they clicked. If they click another ComboBox, it'll focus there, but it won't show its popup. However, I'm sure you could deal with those cases in this event handler if you need to.

    EDIT: Whoops, you're using WPF! Nevermind, then; this is how you'd do it in WinForms. However, you've still got the DropDownClosed event in WPF.

    EDIT 2: This seems to do it. I'm not familiar with WPF so I don't know how robust it is, but it'll focus on a TextBox, for example. This is a default WPF app with a Window called MainWindow. When you close the DropDown of the comboBox, it'll focus the top-most focusable Control at the mouse position that isn't MainWindow:

    private void comboBox_DropDownClosed(object sender, EventArgs e)
    {
        Point m = Mouse.GetPosition(this);
        VisualTreeHelper.HitTest(this, new HitTestFilterCallback(FilterCallback),
            new HitTestResultCallback(ResultCallback), new PointHitTestParameters(m));
    }
    
    private HitTestFilterBehavior FilterCallback(DependencyObject o)
    {
        var c = o as Control;
        if ((c != null) && !(o is MainWindow))
        {
            if (c.Focusable)
            {
                c.Focus();
                return HitTestFilterBehavior.Stop;
            }
        }
        return HitTestFilterBehavior.Continue;
    }
    
    private HitTestResultBehavior ResultCallback(HitTestResult r)
    {
        return HitTestResultBehavior.Continue;
    }
    

提交回复
热议问题