Как найти предыдущий активный элемент управления c # - PullRequest
3 голосов
/ 26 ноября 2009

Я занимаюсь разработкой управления с клавиатуры, очень просто встроенного в форму. используя класс sendkey для ввода символов. чтобы сделать этот функционал, необходимо знать предыдущий выбранный элемент управления.

Ответы [ 6 ]

5 голосов
/ 26 ноября 2009

Что-то вроде следующего должно помочь:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DragDropTest
{
    public partial class LostFocusTestForm : Form
    {
        private Control _lastControl;

        public LostFocusTestForm()
        {
            InitializeComponent();

            TrapLostFocusOnChildControls(this.Controls);
        }
        private void finalTextBox_Enter(object sender, EventArgs e)
        {
            MessageBox.Show("From " + _lastControl.Name + " to " + this.ActiveControl.Name);
        }

        private void AllLostFocus(object sender, EventArgs e)
        {
            _lastControl = (Control)sender;
        }

        private void TrapLostFocusOnChildControls(Control.ControlCollection controls)
        {
            foreach (Control control in controls)
            {
                control.LostFocus += new EventHandler(AllLostFocus);

                Control.ControlCollection childControls = control.Controls;
                if (childControls != null)
                    TrapLostFocusOnChildControls(childControls);
            }
        }
    }
}
2 голосов
/ 26 ноября 2009

Расширяя ответ Дэвида. Вот как вы можете использовать событие Enter и переменную для хранения последнего элемента управления:

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Control lastControlEntered = null;

        public Form1()
        {
            InitializeComponent();

            foreach (Control c in Controls)
                if (!(c is Button)) c.Enter += new EventHandler(c_Enter);
        }

        void c_Enter(object sender, EventArgs e)
        {
            if (sender is Control)
                lastControlEntered = (Control)sender;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = lastControlEntered == null ? "No last control" : lastControlEntered.Name;
        }
    }
}

Чтобы запустить этот код, добавьте несколько текстовых полей и другого элемента управления в форму в Visual Studio, добавьте кнопку и метку и прикрепите обработчик нажатия кнопки к button1_Click. Когда вы нажимаете кнопку, на ярлыке отображается последний элемент управления, в котором вы находились до нажатия кнопки. Отредактируйте этот код в соответствии с вашими потребностями.

0 голосов
/ 01 февраля 2011

Вы можете сделать это string activeControl = this.ActiveControl.Name

0 голосов
/ 26 ноября 2009

Другая стратегия заключается в использовании метода расширения для расширения Control.ControlCollection, а затем с помощью некоторого косвенного (делегата) рекурсивного синтаксического анализа коллекции Controls формы с добавлением специального обработчика «Enter», который обновляет статическую переменную. Отслеживая предыдущий активный контроль и текущий активный контроль, вы получаете то, что вам нужно ... если я полностью понимаю ваш вопрос. Вот пример, который требует FrameWork 3.5 или 4.0.

// в общедоступном статическом классе:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

private static EventHandler _event;

    // extension method on Control.ControlCollection
    public static void SetEnterEvent(this Control.ControlCollection theCollection, EventHandler theEvent)
    {
        _event = theEvent;
        recurseSetEnter(theCollection);
    }

    // recurse all the controls and add the Enter Event :

    public static void recurseSetEnter(Control.ControlCollection aCollection)
    {
        foreach (Control theControl in aCollection)
        {
            // "weed out" things like internal controls of the NumericUpDown Control
            // String.IsNullOrWhiteSpace is FrameWork 4.0
            // use Trim() followed by String.IsNullOrEmpty for FrameWork 3.5
            if (!String.IsNullOrWhiteSpace(theControl.Name))
            {
                Console.WriteLine("setting enter handler for : " + theControl.Name + " : " + theControl.GetType().ToString());

                theControl.Enter += _event;
            }

            if (theControl.Controls.Count > 0) recurseSetEnter((Control.ControlCollection)theControl.Controls);
        }
    }

Так, как мы используем это: в форме:

Сначала давайте определим фактический обработчик события, который будет фактически выполняться при обнаружении события Enter в любом элементе управления:

Мы будем хранить текущий активный элемент управления и предыдущий активный элемент управления в открытых статических переменных:

public static Control theActiveControl = null;

public static Control thePreviousControl = null;

А вот код, который выполняет обновление:

private void control_enter(object sender, EventArgs e)
{
    thePreviousControl = theActiveControl;
    theActiveControl = sender as Control;
    Console.WriteLine("Active Control is now : " + theActiveControl.Name);
}

Теперь в событии Form_Load или в другом месте нам просто нужно подключить события:

// in a Form**

    // define a delegate for the enter Event
    private event EventHandler enter = delegate { };

// in the form load even or somewhere : assign an actual event handler to the delegate
    enter += new EventHandler(control_enter);

Наконец, мы вызываем метод расширения в коллекции элементов управления формы:

this.Controls.SetEnterEvent(enter);

Обсуждение: WinForm поддерживает коллекцию ActiveControl: она будет содержать указатель на последний активированный элемент управления, независимо от того, насколько глубоко он вложен в один или несколько контейнеров: ... некоторые контейнеры (например, панели) не регистрируются как активные элементы управления в этой коллекции, даже если у них есть события Leave / Enter ... элементы управления станут ActiveControl, когда они используются / выбраны / введены / сфокусированы и т. д. К сожалению, событие ActiveControlChanged отсутствует.

[править] на практике я разрабатываю это, используя «фильтры», чтобы я мог выборочно пропустить определенные типы объектов или, например, найти какой-то «ключ» (в имени элемента управления или его теге), чтобы определить, является ли или не добавлять обработчик ... да ... это эксперимент. [Править]

[править] обратите внимание, что некоторые элементы управления, такие как PictureBox, не выставляют событие 'Enter', но этот код не вызывает ошибку: моя долгосрочная цель - найти способ проверить, не задумываясь, действительно ли конкретный элемент управления отображает данное событие перед установкой: я считаю плохой практикой просто позволять вещам, таким как PictureBox, «шевелиться». До сих пор я не нашел правильного «теста» для «контейнера» («оказалось, что ControlContainer» оказался неправильным треком). Также вы можете заметить, что панели, например, предоставляют событие «Enter», но оно запускается только тогда, когда активирован какой-либо элемент управления внутри панели. [Править]

Надеюсь, это полезно. Я уверен, что это, вероятно, можно было бы написать более элегантно, используя лямбды, но пока я «личинка», питающаяся листьями Скита в этом отношении:)

0 голосов
/ 26 ноября 2009

Вы должны отслеживать это самостоятельно. Напишите тривиальный обработчик UIElement.LostFocus, который переводит отправителя в переменную «последний элемент управления с фокусом», и все готово.

ПРИМЕЧАНИЕ: WPF. Не уверен, что вы делаете это или WinForms. В последнее время я так много делаю на WPF, у меня это на уме.

0 голосов
/ 26 ноября 2009

Вам необходимо сохранить его в переменной. Для объектов управления есть событие «Ввод»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...