2009-11-26 3 views

ответ

0

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

2

Расширение ответа Давида. Это, как вы можете использовать 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, и добавить кнопку и ярлык и прикрепите обработчик кликов кнопки к кнопке1_Щелкните. Когда вы нажимаете кнопку, последний элемент управления, в котором вы были, перед нажатием кнопки отображается на этикетке. Отредактируйте этот код в соответствии с вашими потребностями.

+0

Имейте в виду, что этот код не будет работать, если есть элемент управления на контроллере, например, если есть панели или пользовательские элементы управления. В этом случае ваш цикл foreach должен быть рекурсивным и проходить через controls.controls.controls ... и т. Д. – NotDan

+0

Это хороший момент! Я забыл об этом. –

+0

Благодарим вас, кроме того, я использую свойство Items как Control colection для действительных элементов управления. Кроме того, это позволяет перемещать фокус с последнего на первый элемент в коллекции. – volody

-2

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

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

5

Что-то вроде следующей должно сделать трюк:

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); 
      } 
     } 
    } 
} 
0

Другой стратегия заключается в использовании методы расширения для расширения Control.ControlCollection, а затем с помощью какого-то окольного (делегата) рекурсивно разобрать коллекцию штурвала Форма добавляет специальный обработчик «Ввод», который обновляет статическую переменную. Следя за предыдущим Active Control и действующим Active Control, у вас есть то, что вам нужно ... если я полностью понимаю ваш вопрос. Вот пример, который требует 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: она будет содержать указатель на последний активированный элемент управления, независимо от того, насколько глубоко он вложен в один или несколько контейнеров: ... некоторые контейнеры (например, панели) не регистрируются как активные элементы управления в этой коллекции, даже если у них есть события «Оставить/Ввод» ...элементы управления станут ActiveControl, когда они будут использоваться/выбраны/введены в/сфокусированы и т. д. К сожалению, нет события «ActiveControlChanged».

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

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

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

0

Вы можете сделать это по Строка activeControl = this.ActiveControl. Имя

Смежные вопросы