0

У меня есть tabControl, в котором я добавляю tabPages каждый раз, когда нажимаю кнопку поиска. Объект tabControl также имеет обработчик событий для MouseDown, чтобы закрыть вкладку, когда мышь висит на определенной вкладке и нажимает на нее. Метод tabcontrol_MouseDown также отменяет задачу, которая запускается при нажатии кнопки поиска, чтобы задача не пыталась обновить с помощью tabPage, который был удален из tabControl с его resultData.Как получить ссылку на локальную переменную, определенную в методе, изнутри метода обработчика событий? (при отсутствии лучшего заголовка)

Проблема с приведенным ниже кодом состоит в том, что cts является переменной объекта, поэтому она перезаписывается каждый раз, когда я создаю новую вкладку с новым элементом CancellationTokenSource. Это может сработать, если мне нужно только добавить одну вкладку в tabControl, но мне нужно добавить много.

Есть ли способ, которым я мог бы определить и создать токен отмены в методе searchButton_Click, и пусть tabControl_MouseDown найдет ссылку на него или есть другой способ, которым я мог бы это решить?

public class Form1 : Form { 

    CancellationTokenSource cts; 

    private async void searchButton_Click(object sender, EventArgs e){ 

     cts = new CancellationTokenSource(); 

     tabControl1.TabPages.Add(new TabPage()); 
     var resultData = await Task.Run(() => SlowMethod()); 
     if (!cts.Token.IsCancellationRequested) { /* add resultData to tabPage */ } 

    } 

    private void tabControl_MouseDown(object sender, MouseEventArgs e){ 
     // - I select the tab being hovered with mouse 
     // - I remove the tab from tabControl 
     cts.Cancel(); 
    } 
} 
+0

Извините, это была только опечатка, отредактировав вопрос. Речь идет о другом. –

+0

Не можете ли вы просто вывести из 'TabPage', сделать' cts' полем и 'SlowMethod' методом экземпляра? Тогда каждый экземпляр вкладки может иметь свой собственный «CancellationTokenSource». –

+0

@ KirillShlenskiy Я разработал tabPage в дизайнере, потому что мне нужно было иметь конкретное расположение элементов управления внутри него. –

ответ

1

Вы должны держать свои объекты в каком-то глобальное хранилище как Dictionary<int, CancellationTokenSource>, где ключ является идентификатором вы даете вкладки и CancellationTokenSource связанно с этой конкретной вкладкой

Например

public class Form1 : Form { 
    Dictionary<int, CancellationTokenSource> cts = new Dictionary<int, CancellationTokenSource>(); 
    int tabID = 0; 

    private async void searchButton_Click(object sender, EventArgs e){ 

     CancellationTokenSource temp = new CancellationTokenSource(); 

     tabID++;  
     TabPage tp = new TabPage(); 
     tp.Tag = tabID; 
     tabControl1.TabPages.Add(tp); 

     var resultData = await Task.Run(() => SlowMethod()); 
     if (!temp.Token.IsCancellationRequested) { /* add resultData to tabPage */ } 

     cts.Add(tabID, temp); 
    } 

    private void tabControl_MouseDown(object sender, MouseEventArgs e){ 
     // - I select the tab being hovered with mouse 
     // - I remove the tab from tabControl 
     TabPage tp = .... select the tabpage from the mouse position 
     CancellationTokenSource temp = cts[Convert.ToInt32(tp.Tag)] 
     temp.Cancel(); 
    } 
} 

Таким образом, каждая отдельная вкладка будет уникально указана, и соответствующий источник CancellationTokenSource будет введен в словарь и легко извлекаться в требуемый момент.

+0

Вижу, спасибо. Я надеялся на что-то немного лучше, хотя ...:/Это единственный способ? –

+0

Пожалуйста, см. Мой собственный ответ. Думаю, я нашел более легкое решение, просто используя 'Tag'. Как вы думаете? –

2

Основываясь на подсказках, найденных в ответе @Steve Я думаю, что нашел приятное, более простое решение, которое не требует использования глобального объекта для хранения пар ключей значений tabPages и их элементов управления.

Это все, что мне нужно сделать:

public class Form1 : Form { 

    private async void searchButton_Click(object sender, EventArgs e){ 
     CancellationTokenSource cts = new CancellationTokenSource(); 
     TabPage myNewTab = new TabPage(); 
     myNewTab.Tag = cts; 

     tabControl1.TabPages.Add(myNewTab); 
     var resultData = await Task.Run(() => SlowMethod()); 
     if (!cts.Token.IsCancellationRequested) { /* add resultData to tabPage */ } 

    } 

    private void tabControl_MouseDown(object sender, MouseEventArgs e){ 
     // - I select the tab being hovered with mouse 
     // - I remove the tab from tabControl 
     CancellationTokenSource cts = (CancellationTokenSource)tabControl1.SelectedTab.Tag; 
     cts.Cancel(); 
    } 
} 

Кажется, работает, как ожидалось.

+0

Это также жизнеспособное решение. Это проще, но, конечно, он связывает список объектов непосредственно с элементом пользовательского интерфейса. Нет проблем вообще, если вам не нужно манипулировать или обрабатывать этот список вне этой формы. Другими словами, если это когда-либо понадобилось, я предпочел бы перебирать значения словаря вместо TabPages, но я действительно nitpicking здесь – Steve

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

  • Нет связанных вопросов^_^