Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.93/29: Рейтинг темы: голосов - 29, средняя оценка - 4.93
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73

Обращение к элементам формы из другого файла проекта

30.12.2017, 17:19. Показов 6512. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всех с наступающим.
Есть проект, работать в котором стало не особо удобно по причине большого количества кода. Часть кода хочется перенести в другой файл .cs.
Возникает следующая проблема. При попытке вывести текст в элементе формы:

C#
1
BeginInvoke((Action)(() => label0.Text = "Я тут"));
оказывается, что и BeginInvoke, и label0 не существуют в текущем контексте. Как решается данный вопрос по-человечески?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.12.2017, 17:19
Ответы с готовыми решениями:

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

Обращение к элементам формы из другого потока
Извиняйте за очередную тему. Тут на форуме я уже их много прочитал, но все равно не могу понять эти делегаты и инвок. На форуме есть...

Обращение к элементам формы из другого pas файла
Подскажите как обратиться к элементу формы например Combobox1 из другого файла без "Form1.Combobox" а чисто напрямую ComboBox1.

25
 Аватар для netBool
325 / 304 / 173
Регистрация: 16.11.2010
Сообщений: 1,069
Записей в блоге: 9
30.12.2017, 17:39
Цитата Сообщение от dapol Посмотреть сообщение
Часть кода хочется перенести в другой файл .cs.
Дело наверное в том. что часть кода переносится не в другой файл, а в другой класс... Тогда в Action нужно помимо прочего получить ссылку на экземпляр этого класса.


PS: Здесь, видимо, подразумевается, что это форма... тогда можно для получения ссылки на нее воспользоваться, например, свойством Form.Owner
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
30.12.2017, 18:09
ня всякий... Разделяемые классы и методы (Руководство по программированию в C#)
0
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
31.12.2017, 16:27  [ТС]
netBool, да вы все поняли верно, а я объяснил не достаточно подробно. В другом файле другой класс, запускаемый отдельным потоком. Не покажете, как в моем случае пользоваться Form.Owner? То, как попробовал я, не выходит, поскольку Owner, по словам VS не определен.

Wolfdp, за такую штуку спасибо, не знал. Но это не поможет обращаться к элементам формы из другого класса.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
31.12.2017, 19:01
dapol, я с увереностю могу сказать, что нарушен общий принцип аля "разделяй и властвуй", когда сильно много завязок на реализации и общих переменых. У вас должна быть модель данных (реализованая через class), к которой привязывается форма для отображения, и которую можно передать в поток. Т.к. class ссылочный тип данных, то поменяв в отельном потоке, автоматом поменяется и на форме. Чтобы не заморачиватся с event для отслежевания момента изменения данных, можно использовать binding. За примером в гугл.

к прочтению Архитектура ПО в WinForms (FAQ & HowTo) - C#
0
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
11.01.2018, 15:07  [ТС]
Мне кажется, что это вопрос, с которым сталкиваются абсолютно все, чей код состоит из более, чем одного класса, следовательно, для него есть совершенно типичное решение, коим все и пользуются.
Поразмышлял, сделал следующим образом:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class Form1 : Form
{
    ................
    
    public void SetLogText(string text)
    {
        if (tboxLog.InvokeRequired)
        {
            tboxLog.BeginInvoke(new Action(() => { tboxLog.AppendText(text); }));
        }
        else tboxLog.AppendText(text);
    }
}
Теперь я могу пользоваться одним методом и для GUI и для параллельных потоков. Уже хорошо.
Текст выводится в форме ровно до тех пор, пока вывод производится из текущего класса. Однако, если сделать так:
C#
1
2
Form1 form = new Form1();
form.SetLogText("бла бла бла");
Ничего не происходит. Что не предусмотрел?
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
11.01.2018, 16:31
Цитата Сообщение от dapol Посмотреть сообщение
чей код состоит из более, чем одного класса, следовательно, для него есть совершенно типичное решение, коим все и пользуются
И Вам это решение совершенно четко и доступно объяснили в предыдущем посте, по поводу модели данных.
Использование конструкций BeginInvoke() следует очень осторожно, и только в крайних случаях, а не лепить где попало.
К тому же использование процедур класса-формы в другом классе - это говнокод. Процедуры в идеале должны быть private. А еще лучше, если форма вообще ничего не узнает никогда о логике работы приложения (движемся в сторону MVC, MVVM, MVP). В идеале форма - метод отображать что-то откуда-то, используя биндинги/привязки/события. И ей совершенно должно быть неважно откуда данные берутся. Ну разве что базовые правила заполнения/типы данных проверять у себя можно.
0
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
11.01.2018, 17:10  [ТС]
Я уверен, что и уважаемый Wolfdp, и вы объясняете доступно. Дело в том, что доступность на определенных уровнях развития значительно отличается.
Кликните здесь для просмотра всего текста
Это как объяснить ребенку, что в пробке стоять еще два часа, при этом он не знает, что в часе 60 минут, умеет считать только до пяти и слабо представляет себе скоротечность времени. Думаю, метафора понятна. Я пришел сюда с пониманием работы и умением писать что-то для себя на PHP и JavaScript.


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

Цитата Сообщение от hoolygan Посмотреть сообщение
Использование конструкций BeginInvoke() следует очень осторожно, и только в крайних случаях, а не лепить где попало.
Это единственный вариант, который я сумел найти для вывода из параллельного потока. На уровне моих знаний использование потоков просто необходимо, чтобы не висела основная форма, да и в принципе что-то делалось параллельно.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
11.01.2018, 17:35
Цитата Сообщение от dapol Посмотреть сообщение
Ничего не происходит. Что не предусмотрел?
возможно то, что вьі создаете новое окно, а не используете существующее.
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
11.01.2018, 17:48
Цитата Сообщение от dapol Посмотреть сообщение
использование потоков просто необходимо, чтобы не висела основная форма
Потоки для форм уже "как бы" потеряли свой приоритет. Намного приоритетней пользоваться Task-ами.
Понятно, что не всё будет получаться сразу же.
Ссылки на примеры были Вам даны немного ранее - Архитектура ПО. Но научиться идеалу за месяц-два не получится. Но - было бы желание.
На самом деле на официальных страничках документации всегда присутствует код примеров. Для понимания советовал бы Вам его копировать себе в студию, и разбирать вплоть до полного понимания каждой строки кода. Они (примеры) там примитивные, но дают четкое понимание происходящего.
0
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
12.01.2018, 18:43  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
возможно то, что вьі создаете новое окно, а не используете существующее.
Да, признаю, глупость сделал.

Цитата Сообщение от hoolygan Посмотреть сообщение
Потоки для форм уже "как бы" потеряли свой приоритет. Намного приоритетней пользоваться Task-ами.
Делаю тасками, просто называю потоками

Добавлено через 13 минут
Видимо, без какого-либо примера не разберусь. Архитектуру читал, на словах все понятно, но как это применять - не понимаю.
Давайте рассмотрим, например, загрузку файла на FTP:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class FTP 
{
 
public FtpWebRequest connectFtp(string method, string path)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ip/" + path);
    request.Credentials = new NetworkCredential(un, up);
    request.UsePassive = false;
    request.Method = method;
    request.KeepAlive = true;
    request.UseBinary = true;
 
    return request;
}
 
public void UploadFile(string dir, string file)
{
    string filePath = Properties.Settings.Default.mainPath + dir + "\\" + file;
 
    FileInfo fileInf = new FileInfo(filePath);
    long fileSize = fileInf.Length;
    long fileSizeMb = fileSize / 1024 / 1024;
 
    FtpWebRequest request = connectFtp(WebRequestMethods.Ftp.UploadFile, dir + "\\" + file);
 
    int buffLength = 262144;
    byte[] buff = new byte[buffLength];
    int contentLen;
 
    double loaded = 0;
    FileStream fs = fileInf.OpenRead();
 
    Stream strm = request.GetRequestStream();
    contentLen = fs.Read(buff, 0, buffLength);
 
    while (contentLen != 0)
    {
        strm.Write(buff, 0, contentLen);
        contentLen = fs.Read(buff, 0, buffLength);
        loaded += contentLen;
 
        double percent = Math.Floor(loaded / fileSize * 100);
 
        //вот здесь я хочу передавать значение percent куда-нибудь в форму, не столь важно куда именно
    }
 
    strm.Close();
    fs.Close();
}
}
Запутался окончательно...
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
12.01.2018, 18:55
Цитата Сообщение от dapol Посмотреть сообщение
//вот здесь я хочу передавать значение percent куда-нибудь в форму, не столь важно куда именно
event
в самой форме UploadFile запускается в отдельном потоке.
в обработчике event для вывода инфьі на окно нужно пробрасьівать в главную очередь через Control.Invoke

Добавлено через 2 минуты
еще вместо event, в UploadFile можно передавать делегат для обработки каждой итерации.
1
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
15.01.2018, 09:53
Вот, небольшой примерчик, который должен помочь разобраться с биндингом. Почти что твоя ситуация, немного допилить только под нужды.
Вложения
Тип файла: 7z testNotifyProperty.7z (19.3 Кб, 10 просмотров)
1
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
15.01.2018, 16:13  [ТС]
Спасибо, пока разбираюсь. Заодно решил подтянуть теорию, поскольку, как оказалось, нет полного понимания принципов ООП.
1. Верно ли утверждение, что максимальное количество методов в классе должно быть private?
2. Допустим, у меня задача выполнять какие-то действия с файлами на жестком диске, а также примерно тот же набор действий на FTP. Правильно/не правильно: создать два независимых класса, которые работают "сами в себе", даже если часть методов одинакова (условно, метод на проверку существования переменной). Или же создавать отдельный класс с общими методами public, к которым обращаться через экземпляр класса. Вариант лезть вторым классом в первый не рассматриваю, поскольку он не нравится даже мне.
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
15.01.2018, 17:04
1. Я бы так не сказал. Думаю (ИМХО) все методы, что касаются только данного конкретного класса (-экземпляра) должны быть приватными. Т.е. решать проблему инкапсуляции как "закрыть всё, что явно должно быть неоткрыто". т.е. принцип "вытри нос а не дай я тебе нос вытру".
Да по разному можно. Даже вплоть до создания одного статического класса-хелпера, куда вынести все идентичные методы.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
15.01.2018, 17:19
Цитата Сообщение от dapol Посмотреть сообщение
Верно ли утверждение, что максимальное количество методов в классе должно быть private?
Зайдем с другой стороны -- что это нам должно давать?
0
4 / 4 / 2
Регистрация: 12.09.2013
Сообщений: 73
15.01.2018, 18:03  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
Зайдем с другой стороны -- что это нам должно давать?
Я и пытаюсь понять... Насколько я понимаю, принципиальной разницы нет (?):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Program
    {
 
        static void Main(string[] args)
        {
            CheckSum ch = new CheckSum();
            int myInt = ch.Diff();
        }
    }
 
    class CheckSum
    {
        private int x = 5;
        private int y = 4;
 
        private int Summ()
        {
            return x + y;
        }
        private int Multiple()
        {
            return x * y;
        }
        public int Diff()
        {
            return Multiple() - Summ();
        }
    }
вариант 2:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   class Program
    {
 
        static void Main(string[] args)
        {
            CheckSum ch = new CheckSum();
            int summ = ch.Summ();
            int mult = ch.Multiple();
 
            int myInt = mult - summ;
        }
    }
 
    class CheckSum
    {
        private int x = 5;
        private int y = 4;
 
        public int Summ()
        {
            return x + y;
        }
        public int Multiple()
        {
            return x * y;
        }
    }
Возможно, второй вариант кривоватый, либо он работает дольше, чем первый, либо это просто говнокод.
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
15.01.2018, 21:26
В зависимости от бизнес модели использования и 1 и 2 вариант имеют право на жизнь.
Скажем так, если для работы основного кода нужна сумма отдельно, то 2 вариант предпочтительный, если же только разница то однозначно первый.
Но дело в том, что класс вычислений ничего не принимает, соответственно оба варианта говнокодные, так как возвращают константы
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
16.01.2018, 16:55
Цитата Сообщение от hoolygan Посмотреть сообщение
Вот, небольшой примерчик, который должен помочь разобраться с биндингом. Почти что твоя ситуация, немного допилить только под нужды.
а как правильно сделать, чтобы в самом таске менять значение, GUI его подхватывал сразу, а таск не прерывался.
C#
1
2
3
4
5
6
7
8
Task.Run(() =>
            {
            for (int i = 0; i < 10; i++)
                {
                    Thread.Sleep(500);
                    NumOfActivities = i + 1; //ругается на колл к гуи из другого потока
                }
            });
Можно/нужно ли без инвоков это делать и как?
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
16.01.2018, 23:14
КОП, у я же сделал безо всяких invoke(), и прекрасно меняется значение внутри таски, и GUI отображает. В данном примере суть именно в биндинге и реализации интерфейса INotifyPropertyChanged. Именно он производит волшебство в GUI.Такой себе мелкий отклик к MVVM. А иначе придется через ивенты напрямую работать. Суть та же, что и тут, но всю деятельность вручную.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.01.2018, 23:14
Помогаю со студенческими работами здесь

Обращение к элементам формы с другого потока
Есть форма, есть потоки, которые должны получить доступ к ProgressBar'у, расположенному на форме. Делал так: module *** Private...

Обращение к элементам из другого окна
Допустим в окне A происходят расчеты и данные записывается в специальный класс List //окно A public List&lt;string&gt; newlist...

Обращение к элементам активити из другого класса
Добрый день. Ломаю голову битый час, все не могу понять, почему у меня не получается. Опишу по шагам. Создал проект андроид (в эклипсе),...

Обращение к элементам Form из другого класса
Подскажите, будьте добры, как обратиться к элементу Form1 из другого класса. Мне нужно использовать изображение pictureBox1...

Обращение к элементам управления из другого потока. Проблемы с этим.
Не понимаю, что тут не так? Я пытаюсь из другого потока установить свойсво Maximum для ProgressBar. void...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru