Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.93/30: Рейтинг темы: голосов - 30, средняя оценка - 4.93
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
.NET 4.x

Работа файлового менеджера и связанное с ним

09.04.2021, 18:58. Показов 7394. Ответов 66
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тема создана в результате критики архитектуры приложения в теме Модальное Окно для выбора операции с файлами без зависаний при выполнении цикла.

И так. Я начал с нуля программу. Её основой файловый менеджер служит. И очень много вопросов.

Во 1 файловый менеджер должен много каких операций выполнять.
Во 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Linq;
 
namespace Eador_M_of_the_B_W_Launcher
{
    class FileManager
    {
        public enum StopOperation
        {
            sopRunGame,
            sopUncompressingStart,
            sopRunSavesEditor,
            sopCMD,
            sopRunProg
        }
 
        class ProgressInfo
        {
            public ProgressInfo(StopOperation stopOperation)
            {
                this.stopOperation = stopOperation;
            }
 
            public StopOperation stopOperation { get; set; }
            public bool? isStartGame { get; set; }
            public string FileName { get; set; }
            public int? Progress { get; set; }
            public string ErrorMsg { get; set; }
        }
 
        private readonly IProgress<ProgressInfo> progress;
 
        public delegate void EventOutFile(string file);
        public event EventOutFile OutFile;
 
        public delegate void EventProgress(int progress);
        public event EventProgress Progress;
 
        public delegate void EventStop(StopOperation stopOperation, bool isError = false, string error = "");
        public event EventStop Stop;
 
 
        public delegate void EventStartGame();
        public event EventStartGame StartGame;
 
        public FileManager()
        {
            progress = new Progress<ProgressInfo>(OnProgress);
        }
 
        private void OnProgress(ProgressInfo pInfo)
        {
            if (pInfo.isStartGame == true)
            {
                StartGame?.Invoke();
                return;
            }
 
            if (pInfo.FileName != null)
            {
                OutFile?.Invoke(pInfo.FileName);
                return;
            }
 
            if (pInfo.Progress != null && pInfo.Progress.HasValue)
            {
                Progress?.Invoke(pInfo.Progress.Value);
                return;
            }
 
            if (pInfo.ErrorMsg != null && pInfo.ErrorMsg.Length > 0)
                Stop?.Invoke(pInfo.stopOperation, true, pInfo.ErrorMsg);
            else
                Stop?.Invoke(pInfo.stopOperation);
        }
 
        public void UncompressingStart(string pathTrainer, string extSave = "*.map")
        {
            SGeneral.ReSaveFiles();
            new Thread(() =>
            {
                UncompressingDoWork(pathTrainer, SGeneral.saveFiles, extSave);
            }).Start();
        }
 
        public void UncompressingStart(string pathTrainer, List<FileInfo> saves, string extSave = "*.map")
        {
            new Thread(() => { UncompressingDoWork(pathTrainer, saves, extSave); }).Start();
        }
 
        private void UncompressingDoWork(string pathTrainer, IList<FileInfo> files, string extSave)
        {
            try
            {
                for (int i = 0; i < files.Count; i++)
                {
                    string file = files[i].FullName;
 
                    progress.Report(new ProgressInfo(StopOperation.sopUncompressingStart) { FileName = file });
 
                    Cmd(true, false, $"eador.exe \"{file}\"", pathTrainer);
                    var prc = Convert.ToInt32(Convert.ToSingle(i + 1) / Convert.ToSingle(files.Count) * 100);
 
                    progress.Report(new ProgressInfo(StopOperation.sopUncompressingStart) { Progress = prc });
                }
 
                progress.Report(new ProgressInfo(StopOperation.sopUncompressingStart));
            }
            catch (Exception ex)
            {
                progress.Report(new ProgressInfo(StopOperation.sopUncompressingStart) { ErrorMsg = ex.Message });
            }
        }
 
        public void RunGameEador()
        {
            new Thread(() =>
            {
                try
                {
                    var isSteamVersion = SGeneral.settings.fileNameGame.Contains("steamapps");
                    if (isSteamVersion)
                    {
                        Process.Start("steam://rungameid/232050");
                        List<Process> processes;
 
                        do
                        {
                            processes = Process.GetProcessesByName("launcher").ToList();
                        } while (processes.Count <= 0);
 
                        progress.Report(new ProgressInfo(StopOperation.sopRunGame) { isStartGame = true });
 
                        processes.ForEach(x => 
                        {
                            x.WaitForExit();
                        });
 
                        Thread.Sleep(1500);
 
                        processes = Process.GetProcessesByName("eador_mbw").ToList();
                        if (processes.Count > 0)
                        {
                            processes.ForEach(x =>
                            {
                                x.WaitForExit();
                            });
                        }
 
                        processes.Clear();
 
                        progress.Report(new ProgressInfo(StopOperation.sopRunGame));
                    }
                    else
                    {
                        StartGame.Invoke();
                        ProcessHelper.StartProcessAndWaitForAllChildrenToExit(SGeneral.settings.fileNameGame, "", Path.GetDirectoryName(SGeneral.settings.fileNameGame));
                        progress.Report(new ProgressInfo(StopOperation.sopRunGame));
                    }
                }
                catch (Exception ex)
                {
                    progress.Report(new ProgressInfo(StopOperation.sopRunGame) { ErrorMsg = ex.Message });
                }
 
            }).Start();
        }
 
        public void RunSavesEditor(string fileNameSave = "")
        {
            new Thread(() =>
            {
                try
                {
                    if (!File.Exists(fileNameSave))
                        fileNameSave = SGeneral.settings.pathSaves + SGeneral.settings.saveOskolok;
                    Cmd(true, false, $"eador.exe \"{fileNameSave}\"", $@"{SGeneral.pathProg}\DATA\Trainer");
                    if (File.Exists($@"{SGeneral.pathProg}\DATA\Trainer\config.xml"))
                    {
                        File.SetAttributes($@"{SGeneral.pathProg}\DATA\Trainer\config.xml", FileAttributes.Normal);
                        File.Delete($@"{SGeneral.pathProg}\DATA\Trainer\config.xml");
                    }
                    string config = $"<?xml version=\"1.0\" ?>{Environment.NewLine}<eador_trainer_config>{Environment.NewLine}" +
                            $"\t<eador_save_file_path>{fileNameSave}</eador_save_file_path>{Environment.NewLine}</eador_trainer_config>";
                    File.WriteAllText($@"{SGeneral.pathProg}\DATA\Trainer\config.xml", config);
                    File.SetAttributes($@"{SGeneral.pathProg}\DATA\Trainer\config.xml", FileAttributes.ReadOnly);
 
                    Cmd(true, false, $"java -jar \"{SGeneral.pathProg}\\DATA\\Trainer\\EadorTrainer_1.2.1_compact.jar\"", $@"{SGeneral.pathProg}\DATA\Trainer");
 
                    progress.Report(new ProgressInfo(StopOperation.sopRunSavesEditor));
                }
                catch (Exception ex)
                {
                    progress.Report(new ProgressInfo(StopOperation.sopRunSavesEditor) { ErrorMsg = ex.Message });
                }
 
            }).Start();
        }
 
        public void Cmd(bool isWait, bool isTheread, string arguments, string workingDirectory = "")
        {
            if (isWait && isTheread)
            {
                new Thread(() =>
                {
                    try
                    {
                        Process.Start(new ProcessStartInfo { FileName = "cmd", Arguments = $"/c {arguments}", WorkingDirectory = workingDirectory, WindowStyle = ProcessWindowStyle.Hidden }).WaitForExit();
                        progress.Report(new ProgressInfo(StopOperation.sopCMD));
                    }
                    catch (Exception ex)
                    {
                        progress.Report(new ProgressInfo(StopOperation.sopCMD) { ErrorMsg = ex.Message });
                    }
                }).Start();
            }
            else if (isWait)
                Process.Start(new ProcessStartInfo { FileName = "cmd", Arguments = $"/c {arguments}", WorkingDirectory = workingDirectory, WindowStyle = ProcessWindowStyle.Hidden }).WaitForExit();
            else
                Process.Start(new ProcessStartInfo { FileName = "cmd", Arguments = $"/c {arguments}", WorkingDirectory = workingDirectory, WindowStyle = ProcessWindowStyle.Hidden });
        }
 
        public void RunProg(bool isWait, bool isTheread, string filename, string arguments = null, string workingDirectory = null)
        {
            if (!File.Exists(filename))
                return;
 
            if (isWait && isTheread)
            {
                new Thread(() =>
                {
                    try
                    {
                        ProcessHelper.StartProcessAndWaitForAllChildrenToExit(filename, arguments, workingDirectory);
                        progress.Report(new ProgressInfo(StopOperation.sopRunProg));
                    }
                    catch (Exception ex)
                    {
                        progress.Report(new ProgressInfo(StopOperation.sopRunProg) { ErrorMsg = ex.Message });
                    }
 
                }).Start();
            }
            else if (isWait)
                ProcessHelper.StartProcessAndWaitForAllChildrenToExit(filename, arguments);
            else
                Process.Start(new ProcessStartInfo { FileName = filename, Arguments = arguments, WorkingDirectory = workingDirectory });
        }
    }
}


Но мне он сам не нравится особо так как взаимодействие с таким классом довольно таки тяжелая.

И так. Сама реализация методов останется не изменным так как они исполняют именно то что нужно.
Но надо сделать так чтобы взаимодействия с файловым менеджером была легкой.
И от сюда проблемы у этого. Во 1 операции может выполнятся сразу несколько и паралельно.
Основной операцией служит распаковка сохранений. Другое дело что в этот момент может также выполнятся и запуск игры (Который блин ну очень долгий и разделен на 2 этапа (1 - Игра запускается. 2 - Игра запущена))
и запуск редактора (который имеет этап редактор запущен)
Основная проблема это отображение информации. Здесь я использую 1 класс и (наверное все же это ошибка)
Вот приоритет отображение информации:
1. Распаковка сохранений
2. Запуск игры или игра запущена
3. Информация о запущенных других процессов.
И от сюда вытекает то что у окна для этого всего 3 элемента.
1 Это отображения процента распаковки или загаловка о том что игра запускается или запущена.
2 Это полоска которая в 1 случае отображает процент распаковки в виде полоски а в остальных случаях используется просто как бегущий ползунок
3. Это текстовое поле но уже конкретно под распаковку.
И также Файловому менеджору нужны данные (Параметры) игры которые конечно хранятся в отдельном классе settings и вот тут тоже не понятно. Их конечно можно передать в методы но с другой стороны хотелось бы сами данные сделать глобальными чтобы сами методы смогли получить доступ к данным. Данные конечно нельзя хранить в файловом менеджере так как они использоваться будут не только там.

Добавлено через 9 минут
И так. Есть вариант разделить операции под отдельные классы тоесть запуск игры отдельный класс. Запуск редакторов отдельный. Распаковка отдельный и запуск файлов тоже отдельный и создавать отдельные объекты для каждой операции соотвественно описать события которые повторятся будут в интерфейсе но с другой стороны это весьма затратно по памяти к томуже это все равно не решает приоритетов выполнения отображения информации о выполнении операций. Сами операции должны выполнятся паралельно это важно.

Добавлено через 18 минут
И более подробно о каких данных идет речь:
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
namespace Eador_M_of_the_B_W_Launcher.DataModel.DATA
{
    public class DATAGame
    {
        /// <summary>
        /// Задать настройки по новой
        /// </summary>
        public bool ReSetDATAGame { get; set; }
 
        /// <summary>
        /// Файл с сохранением в Астрале
        /// </summary>
        public string FileNameSaveAstral { get; set; }
        /// <summary>
        /// Файл с сохранением на Осколке
        /// </summary>
        public string FileNameSaveOskolok { get; set; }
        /// <summary>
        /// Файл игры (Полный путь и имя файла)
        /// </summary>
        public string FullNameGame { get; set; }
        /// <summary>
        /// Папка с сохранениями
        /// </summary>
        public string SaveFolder  { get; set; }
        /// <summary>
        /// Файл hex редактора (Полный путь и имя файла)
        /// </summary>
        public string FullNameHexEditor { get; set; }
    }
}
Это модель данных с данными игры. Вот именно она и должна быть глобальной. Также объект этого класса будет серилизоваться и десерилизоваться в JSON
И список с сохранениями уже нужно создавать после того как данные загружены. Так как я говорил что данные эти и сам список должен быть глобальными то хранить объект с этими данными в cs окна отметаем. Но с друго йстороны где это вообще хранить. И вообще производить загрузка данных и запрос на данные если они отсуствуют.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.04.2021, 18:58
Ответы с готовыми решениями:

Шаблон файлового менеджера
Приветствую Уважаемые коллеги! Может есть у кого на примете шаблон файлового менеджера? Хочу что то похожее как в open cart. ...

Разработка файлового менеджера
Доброго времени суток, уважаемые форумчане! Есть файловый менеджер, работает копирование и перемещение файлов из каталогов, думал что этого...

Реализация файлового менеджера
Нужно сделать программу что-то вроде &quot;Файлового менеджера&quot;(Упрощённый, то есть отображение структуры файлов, функции такие как: копировать,...

66
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
19.04.2021, 20:36
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Wolfdp Посмотреть сообщение
Не стоит путать либу с логикой приложения, и либу с компонентами формы.
А что такое MessageBox?
У меня нет пока полного понимания требуемой функциональности приложения, но из того что понял, парсинг данных для настройки производится однократно при запуске приложения.
И он никак не связан никакой логикой с другой функциональностью приложения.

То есть это что-то типа кастомной реализации Properties.Settings.Default.
По сути этот тип содержит в себе отдельную ветку приложения в которой полностью инкапсулирована логика работы с настройками.
В том числе этот тип можно использовать и как Модель, и как View Model, и для прямых привязок в View.
См. Запись из ViewModel в Setting.Properties (странность)

Почему же нельзя сделать свой такой же тип?

Ещё раз - я не утверждаю, что в данном случае это действительно будет правильным решения.
Я не настолько понимаю общую логику функционирования приложения и все связи в нём, чтобы делать категоричные выводы.
Но в общем случае, это вполне допустимый вариант.

Добавлено через 2 минуты
Цитата Сообщение от Wolfdp Посмотреть сообщение
Я не про уровни, а что можно не выносить мозг на старте биндингом данных и команд. Хотя переделывать потом будет весело.
Ок.
Понял.
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
21.04.2021, 17:19  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Дело не в паттернах.
Возьмите для примера MessageBox.
Вы обращаетесь к его СТАТИЧЕСКОМУ методу, который возвращает РЕЗУЛЬТАТ ДИАЛОГА.
Так же и вам следует поступить.
Конструкторы экземпляров надо инкапсулировать.
Добавить статический метод получающий в параметрах нужные значения: имя и расположение файла, ссылки на сервисы, контейнер для возврата полученных данных и др.
А возвращает метод результат выполнения диалога: успешно, ошибка и др.
Добавлено через 2 минуты
Диалог этот будет вызываться в App.Startup и по его результату App будет принимать решение о продолжение работы или завершении с ошибкой.
Не совсем понял. Ну с закрытием программы наверное прийдется пилить отдельную библиотеку ошибок аналогично MessageService
А вот с диалоговыми окнами выбора файлов / папок вот тут без понятия.
Я не могу выносить диалоговые окна выбора файлов / папок в главное окно потому что они должны вызываться только в том случае если данные игры из JSON небыли загружены.
А загрузку данных я произвожу все также в DATAGame_Library
DATAGame_Library это библиотека чтисто для получения и доступ к данным игры. Неважно к каким именно но она получает и хранит их в памяти для быстрого доступа. Например файловому менеджеру от туда нужно путь к игре для запуска игры. Или список сохранений для расшифровки сохранений чтобы их можно было редактировать.
Также не понятно как сделать само закрытие программы. Если делать через событие ошибок и в случиях критических закрывать программу то нужно создавать отдельную библитеку ошибок. Думаю хороший вариант. Можно будет пользоваться в других программах но надо само событие тогда поместить в интерфейс а событие делается через делигат вот его я в интерфейс и не могу засунуть. С другой стороны даже не знаю. Целую библиотеку из за одного события так как ошибка это одно событие которое будет возвращать:
1. Тип ошибки
Warning (Предупреждение) - Все ошибки которые не будут мешать работе программы
Error или Critical Error - Ошибки из за которых работа программы станет невозможным. Естественно при таких результатах программа должна полностью прекратить работу включая все потоки созданные программой.
2. Заголовок ошибки.
3. Текст с ошибкой.
Но как уже сказал это 1 событие и ради этого делать библиотеку даже не знаю но с другой стороны я смогу эту библиотеку юзать в любом месте.

Добавлено через 5 минут
На счет стандартных Properties.Settings то нет. Терпеть не могу c#'арповский Properties.Settings тупо потому что мусорка в системе так сказать ибо сохраняет данные фиг пойми где. Ладно я могу узнать где именно но а если комп чужой. А программа переносная всеже. Да и я люблю для хранения данных JSON а если это картинки или какието файлы то bin
Так что использую серилизацию и десерилизацию так как очень удобно хоть и есть некоторые просадки по скорости но они не заметные. Всеже данные занимают всего то 1 КБ места. Даже меньше.

Добавлено через 2 минуты
Вот сами файлы они да. Много весят но путь к ним это всеголишь строка так что весит очень мало. Списки они не должны сохраняться. Просто в памяти висеть чтоб бес конца их не грузить.

Добавлено через 9 минут
Цитата Сообщение от Wolfdp Посмотреть сообщение
//ну либо 100500 OpenFileDialog, я бы все же набрал окно где можно задать все параметры сразу
Каких блин 100500 диалогов. Всего 2. Выбор папки и выбор файла. Я просто меняю у них заголовок и Фильтр.
Да. Конечно удобно свое диалоговое окно сделать чтобы выбрать все это проблема только в том что с ним возьни будет просто завались. Всеже у меня создания своего диалогового окна ну 1 день минимум если не больше. Во 1 это код а вторых это свое оформление делать и то это занимает без модели данных. С моделью данных будет гораздо сложнее.
Так что гораздо проще мне просто юзать 2 диалога. Выбор файлов и выбор папки.
Кокрас с оформлением у меня все очень плохо. Могу и 10 часов просидеть и все пойдет на помойку.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
21.04.2021, 17:35
Alexandr_7, я возможно не так вас понял.

Из предыдущих сообщений, я понял, что при загрузке вашего приложения сразу вызывается диалог загрузки настроек.
Диалог этот никак не связан с другой логикой приложения, он просто создаёт экземпляр с данными настроек.
Если загрузка настроек не была успешна, то происходит выход из приложения Environment.Exit(0);.

Это так?
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
21.04.2021, 19:01  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Из предыдущих сообщений, я понял, что при загрузке вашего приложения сразу вызывается диалог загрузки настроек.
Диалог этот никак не связан с другой логикой приложения, он просто создаёт экземпляр с данными настроек.
Если загрузка настроек не была успешна, то происходит выход из приложения Environment.Exit(0);.
Это так?
Не настроек а данных игры но в целом так. Да. При загрузке прям сразу грузит и также можно обновить данные что перезагрузка данных идет.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
21.04.2021, 20:54
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Не настроек а данных игры но в целом так. Да.
Я так и понял.

Получается этот диалог можно оформить в виде отдельно проекта не связанного с остальными.
По его результату можно будет принять решение о продолжении работы приложения или прекращении.
Так же он должен вернуть некий контейнер с данными игры и на этом всё его взаимодействие с остальным приложением прекращается.
Так?
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
22.04.2021, 10:46
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Ну с закрытием программы наверное прийдется пилить отдельную библиотеку ошибок
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Получается этот диалог можно оформить в виде отдельно проекта не связанного с остальными.
Не ребята, вы явно упоролись. Серьезно. Плодить lib на ровном месте в проекте на две-три сотни строчек кода? Зачем весь этот Hello world enterprise? Опуская тот момент, что и либы выглядят скорее как модули, потому как тот же IMessageService вшит внезапно MessageLib, а значит основная либа ссылает на реализацию(!) вывода сообщения. Зачем все эти пляски, если вы все равно пишете какую-то чушь?

Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Конечно удобно свое диалоговое окно сделать чтобы выбрать все это проблема только в том что с ним возьни будет просто завались.
1 - "возни" там минут на час. Два текстовых поля, справа кнопка вызова диалогового окна выбора файла. Еще две кнопки "ok-cancell" внизу. Поле с моделью (либо 100500 других способов передачи).
2 - вы тратите время на какие-то "сверхправильные архитектуры", но при этом боитесь потратить лишний час на то чтобы сделать программу удобней?
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
22.04.2021, 11:28
По времени сообщению можете чекнуть сколько занимает набрать с нуля, то что я советую (включая диалоговое окно). В целом можете и дальше заниматся создавание еще одних либ исключительно ради ничего, при этом оставляя железобетоные завязки на wpf.
Вложения
Тип файла: zip Nya.Example.CyberForum2811400.zip (35.4 Кб, 3 просмотров)
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 11:39  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
1 - "возни" там минут на час. Два текстовых поля, справа кнопка вызова диалогового окна выбора файла. Еще две кнопки "ok-cancell" внизу. Поле с моделью (либо 100500 других способов передачи).
2 - вы тратите время на какие-то "сверхправильные архитектуры", но при этом боитесь потратить лишний час на то чтобы сделать программу удобней?
Ну для кого быстро а для меня долго. Потом с ней разбирусь. Пока воспользуюсь стандартными. Тем более пилить свое прийдется пилить какойто файловый менеджер который бут оьтображать файлы и папки. Я не в никакал в это. Да и как оформить я не знаю. А если делать контейнер в котором тнеже самые диалоги OpenFile и выбор папки то ну и за чем это. А пилить свой это еще придумай как объеденить 2 диалога и пиши заново то что за тебя уже написали.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Получается этот диалог можно оформить в виде отдельно проекта не связанного с остальными.
По его результату можно будет принять решение о продолжении работы приложения или прекращении.
Так же он должен вернуть некий контейнер с данными игры и на этом всё его взаимодействие с остальным приложением прекращается.
Так?
Не понял. У меня были идеи сделать событие ошибки в отдельном классе где 3 параметра. Тип ошибки, Заголовок ошибки, Текст ошибки
Срабатывания будет ну например в App.xaml или вынести в отдельное скрытое окно куда будет выводится журнал и при необходимости окно можно сделать видимым.
Если ошибка критическая на пример не указаны нужные данные то просто прекращаем работу программы.
Но у вас какойто другой способ. Не понял вас. Просто конструктор возвращать значения не может. А загрузку данных мне не хочется делать в главном приложения так как не относится к нему. Относится чисто к данным игры которые в отдельной библиотеки.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
22.04.2021, 11:53
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Не понял.
Идея такая: раз загрузка данных для игры не связанна никак с остальной логикой приложения, реализовать это в виде статического метода (по аналогии с MessageBox.Show()), в котором будет инкапсулирована вся логика диалога.
Метод возвращает результаты своего выполнения и загруженные данные.
Код который вызвал этот метод (CB App) по результатам выполнения метода уже сам решит что надо делать дальше: продолжить работу, вывести сообщение об ошибке, выйти из приложения и т.д.

Добавлено через 2 минуты
Цитата Сообщение от Wolfdp Посмотреть сообщение
Плодить lib на ровном месте в проекте на две-три сотни строчек кода?
Можно и не делать отдельный проект, но не вижу что в этом криминального.
Даже если там будет десяток строк кода.
Отдельный проект, в первую очередь, помогает избавиться от проникновения паразитных зависимостей.
При недостатке опыта или в больших проектах, где это трудно контролировать, намного проще сделать отдельный проект, чем потом искать причину случайных ошибок.
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 12:02  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
По времени сообщению можете чекнуть сколько занимает набрать с нуля, то что я советую (включая диалоговое окно). В целом можете и дальше заниматся создавание еще одних либ исключительно ради ничего, при этом оставляя железобетоные завязки на wpf.
Ну про такой контейнер я в курсе ток не знаю есть ли особый смысл в нем.
Во вторых на счет MessageService. Интерфейс в 1 месте класс в другом. Не можно конечно и даже нужно в некоторых ситуациях но у меня данная блиблиотека скорее всего будет использоваться в других проекта поэтому и класс и интерфейс в 1 библиотеки будут находится.
2. Не нужно в 1 библиотеку пихать и файловый менеджер и данные игры так как файловый менеджер космвенно с ними связан а если точнее то практически вообще не связан. С другой стороны наверное может стоит и объеденить так как все равно будет использоваться только в 1 проекте. Ладно. Переименую библиотеку и объеденю.
Но в любом случае не знаю на сколько этот проект по стандартам MVP

Добавлено через 7 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Идея такая: раз загрузка данных для игры не связанна никак с остальной логикой приложения, реализовать это в виде статического метода (по аналогии с MessageBox.Show()), в котором будет инкапсулирована вся логика диалога.
Ну примерно знаю как устроен. MessageBox статический класс по идеи. Но у себя обойтись статическим методом.

Его в томже классе оставлять или в отдельный выносить?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Метод возвращает результаты своего выполнения и загруженные данные.
Тоесть возвращать целый класс данных? Или возврат через параметры делать?

Ведь это не 1 строка. Возвращать необходимо 5 строк.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
22.04.2021, 12:14
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
То есть возвращать целый класс данных? Или возврат через параметры делать?
Если структура данных неизменна "на вечно", то экземпляр типа (класса или структуры).
Если есть вероятность изменения, расширения данных, то либо Dictionary<string, object>, либо просто object.

Возвращать метод будет результат выполнения: успешно, ошибка и т.п.
Сами данные через out-параметр.

Добавлено через 2 минуты
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Его в том же классе оставлять или в отдельный выносить?
Как вам удобнее.
Лично я обычно делаю в том же классе.
Так как конструктор экземпляра скрываю (экземпляр MessageBox вы же не можете создать), и обратиться к нему можно только из статического метода этого же класса.
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 12:35  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Возвращать метод будет результат выполнения: успешно, ошибка и т.п.
Ну пока bool можно будет обойтись. Потом при необходимости добавить enum и возвращать его.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Как вам удобнее.
Лично я обычно делаю в том же классе.
Так как конструктор экземпляра скрываю (экземпляр MessageBox вы же не можете создать), и обратиться к нему можно только из статического метода этого же класса.
Ну вообще метод загрузки должен быть публичным так его можно будет вызывать и через окно. Кнопка Обновление данных делает полную перезагрузку и наверное даже повторно будет запрашивать данные. Навероное вынесу в отдельный статический класс для удобства.

Добавлено через 11 минут
Только щас понял минус. Мне параметром прийдется весь класс возвращать ибо сама загрузка это Десерилизация класса из JSON
Или парсить вручную что не совсем удобно.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
22.04.2021, 12:47
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Мне параметром прийдется весь класс возвращать ибо сама загрузка это Десерилизация класса из JSON
В out параметре.
Это типовой для Шарпа способ.
Что вас смущает?
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 13:33  [ТС]
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
public interface IDataGame
    {
        //Данные игры
        DATAGameModel DATAGameModel { get; set; }
 
        //Проверка на (Является ли игра Steam версией)
        bool IsGameSteam { get; }
        //Проверка на наличия файла сохранения Астрала (Если выбран файл по умолчанию)
        bool IsFileNameSaveAstral { get; }
        //Проверка на наличия файла сохранения Осколка (Если выбран файл по умолчанию)
        bool IsFileNameSaveOskolok { get; }
    }
 
    public class DataGame : IDataGame
    {
        /// <summary>
        /// Интерфейс сервиса сообщений
        /// </summary>
        private readonly IMessageService _messageService;
 
        /// <summary>
        /// Данные игры
        /// </summary>
        public DATAGameModel dataGameModel = new DATAGameModel();
 
        #region Свойства
 
        public DATAGameModel DATAGameModel { get => dataGameModel; set => dataGameModel = value; }
 
        public bool IsGameSteam => dataGameModel.FullNameGame.Contains("steamapps");
 
        public bool IsFileNameSaveAstral => File.Exists(dataGameModel.SaveFolder + dataGameModel.FileNameSaveAstral);
 
        public bool IsFileNameSaveOskolok => File.Exists(dataGameModel.SaveFolder + dataGameModel.FileNameSaveOskolok);
 
        #endregion
 
        public DataGame(IMessageService _messageService)
        {
            this._messageService = _messageService;
        }
 
        ~DataGame()
        {
            SLoadDATAGame.SaveDATAGame(dataGameModel);
        }
    }
 
    static class SLoadDATAGame
    {
 
        /// <summary>
        /// Имя файла сохранения / загрузки данных игры
        /// </summary>
        private const string fileNameDATAGame = @"\DataGame.json";
 
        public static bool LoadDATAGame(bool isSetDataGame, out DATAGameModel oDATAGameModel)
        {
            if (File.Exists(Environment.CurrentDirectory + fileNameDATAGame) && !isSetDataGame)
            {
                var _dataGameModel = JsonSerializer.Deserialize<DATAGameModel>(File.ReadAllText(Environment.CurrentDirectory + fileNameDATAGame), new JsonSerializerOptions { IgnoreNullValues = true });
 
                if (_dataGameModel.IsSetDATAGame)
                {
                    var _dataGameModel2 = _dataGameModel;
 
                    if (SetDATAGame(out _dataGameModel2))
                        _dataGameModel = _dataGameModel2;
                }
 
                oDATAGameModel = _dataGameModel;
 
                return true;
            }
            else
            {
                var _dataGameModel = new DATAGameModel();
 
                if (SetDATAGame(out _dataGameModel))
                {
                    oDATAGameModel = _dataGameModel;
                    return true;
                }
                else
                {
                    oDATAGameModel = null;
                    return false;
                }
 
            }
        }
 
        private static bool SetDATAGame(out DATAGameModel oDATAGameModel)
        {
 
            #region OpenFileDialog
 
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Multiselect = false,
                ValidateNames = true,
                CheckFileExists = true,
                CheckPathExists = true,
                DereferenceLinks = true,
            };
 
            #endregion
 
            #region Задать полный путь к файлу игре
 
            openFileDialog.Filter = "launcher.exe|launcher.exe";
            openFileDialog.DefaultExt = "launcher.exe";
            openFileDialog.Title = "Выберите launcher.exe в папке с игрой";
 
            oDATAGameModel = new DATAGameModel();
 
            oDATAGameModel.FullNameGame = (openFileDialog.ShowDialog() == DialogResult.OK) ? openFileDialog.FileName : null;
 
            if (openFileDialog.ShowDialog() == DialogResult.OK)
                oDATAGameModel.FullNameGame = openFileDialog.FileName;
            else
                return false;
 
            #endregion
 
            #region BetterFolderBrowser
 
            var betterFolderBrowser = new BetterFolderBrowser
            {
                Multiselect = false,
                RootFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Title = "Выберите папку с сохранениями"
            };
 
            #endregion
 
            #region Задать папку сохранений
 
            if (betterFolderBrowser.ShowDialog() == DialogResult.OK)
                oDATAGameModel.SaveFolder = betterFolderBrowser.SelectedFolder;
            else
                return false;
 
            #endregion
 
            #region Задать сохранение Осколка (Не обязательные данные для работы программы)
 
            openFileDialog.Filter = "Сохранение(*.map)|*.map";
            openFileDialog.DefaultExt = "*.map";
            openFileDialog.Title = "Выберите постоянное сохранение с данными осколка";
            openFileDialog.InitialDirectory = oDATAGameModel.SaveFolder;
 
            if (openFileDialog.ShowDialog() == DialogResult.OK)
                oDATAGameModel.FileNameSaveOskolok = openFileDialog.FileName;
 
            #endregion
 
            #region Задать сохранение Астрала (Не обязательные данные для работы программы)
 
            openFileDialog.Filter = "Сохранение(*.map)|*.map";
            openFileDialog.DefaultExt = "*.map";
            openFileDialog.Title = "Выберите постоянное сохранение с данными астрала";
            openFileDialog.InitialDirectory = oDATAGameModel.SaveFolder;
 
            if (openFileDialog.ShowDialog() == DialogResult.OK)
                oDATAGameModel.FileNameSaveAstral = openFileDialog.FileName;
 
            #endregion
 
            #region Задать HEX Редактор (Не обязательные данные для работы программы)
 
            openFileDialog.Filter = "HEX Редактор(*.exe)|*.exe";
            openFileDialog.DefaultExt = "*.exe";
            openFileDialog.Title = "Выберите hex редактор для редактирование сохранений вручную";
 
            if (openFileDialog.ShowDialog() == DialogResult.OK)
                oDATAGameModel.FullNameHexEditor = openFileDialog.FileName;
 
            #endregion
 
            return true;
        }
 
        public static void SaveDATAGame(DATAGameModel dataGameModel)
        {
            File.WriteAllText(Environment.CurrentDirectory + fileNameDATAGame, JsonSerializer.Serialize(dataGameModel, new JsonSerializerOptions { WriteIndented = true, IgnoreNullValues = true }));
        }
    }
Ну даже не знаю. Наверное неправильно сделал но в любом случае мне это не объясняет как закрыть программу если данные небыли загружены. Проще говоря если LoadDATAGame возвращает false
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
22.04.2021, 13:39
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
но в любом случае мне это не объясняет как закрыть программу если данные небыли загружены. Проще говоря если LoadDATAGame возвращает false
Вы где обращаетесь к это методу? В CB App?

Там же, при обращении, проверяете результат и, если надо, закрываете приложение.
Для App - это дозволенный функционал.

Добавлено через 3 минуты
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Ну даже не знаю. Наверное неправильно сделал но...
Не понял оболочки LoadDATAGame, которая ничего не делает кроме вызова GetDataGame.
Почему сразу не вызвать GetDataGame?
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 13:45  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вы где обращаетесь к это методу? В CB App?
Там же, при обращении, проверяете результат и, если надо, закрываете приложение.
Для App - это дозволенный функционал.
Ну в этом и вопрос где вызывать LoadDATAGame? Если в App то и сам объект DATAGameModel нужно выносить в App

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не понял оболочки LoadDATAGame, которая ничего не делает кроме вызова GetDataGame.
Почему сразу не вызвать GetDataGame?
Уже исправил.
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
22.04.2021, 13:49
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Отдельный проект, в первую очередь, помогает избавиться от проникновения паразитных зависимостей.
Вот только глядя на репозиторий и обсуждение, вы делается с точностью до наоборот. IMessageService и реализация MessageService в однйо либе, подразумевающая что это WPF. И да -- куча проектов это фигня:
- будете развлекатся с постоянным подключение очередной библиотеке к проекту
- нельзя сделать замыкание между двумя типами, если они в разных либах.
- собирать потом весь этот зооопарк в том же TeamCity тоже весело (хотя это не ваш случай, но вроде же намылились делать по нормальному?)
- если на практике нужно будет подложить другую версию, то одним файлом это делаеть проще.

Учитывая что ваши мелкие либы в отрыве от основного проекта не шибко из себя что-либо представляют -- смысл вообще выносить отдельно?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
При недостатке опыта или в больших проектах, где это трудно контролировать, намного проще сделать отдельный проект, чем потом искать причину случайных ошибок.
Для контроля, нужно не дробить на 100500 запчастей (которые еще и самостоятельно из себя ничего не представляют), а продумать структуру кода и применить адекватные практики/патерны.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
реализовать это в виде статического метода
где-то в сторонке плачит IoC на пару с DI...

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если есть вероятность изменения, расширения данных, то либо Dictionary<string, object>, либо просто object.
Ужс... во-первых изменения данных уже подразумевает переписывание кода, так что ваш словарь погоды не сделает, во-вторых модель данных проще читать и спасает от неправильного касат, в отличии от object. Вы бы еще dynamic предложили. Максимум где таким развлекаются -- таблица параметров в sql, либо иное хранилище не позволяющее напрямую серилиазовать класс с полями (скажем asp.net сессия).

Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Не нужно в 1 библиотеку пихать и файловый менеджер и данные игры так как файловый менеджер космвенно с ними связан а если точнее то практически вообще не связан.
Сервис/менеджер/контрол, и не связан с моделью данных? Даже не смешно. Вы сначала пишете "мне сложно работать с моим говнокодом", а когда вам предлагают вменяемое решение -- "это не правильно". Вы уверены?

Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Но в любом случае не знаю на сколько этот проект по стандартам MVP
Ваша библиотека -- это менеджер, и является business layer (BL). MVP это клиентская часть и условный пресентер будет использовать ваш FileManager. BL ничего не должен знать об том где он будет работать (WPF, WinForms, Web, Mobile), но при этом быть самодостаточным проектом (т.е. подключив его, я могу сразу работать с файлами).

Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Тем более пилить свое прийдется пилить какойто файловый менеджер который бут оьтображать файлы и папки.
Вас по ходу хлебом не корми, дай чего-либо "запилить в либу". Это тупо 1 окно, с N-полями в которых нужно указать значения. Если такое окно для вас "слишком сложно", то встречный вопрос -- на кой вам вообще программирование? Вам самим будет приятно пользоватся этим подельем? Каждый раз при вызове программы наблюдать картину из постоянно появляющихся окон, вместо единых настроек? Причем такое окно можно будет в одну строчку переиспользовать на главном окне, если пользователь захочет поменять параметры. Нужно добавить новое значение? Добавили в модель свойство, в окне -- новое поле. Все, ничего сложного.

Ну и так:
1. Почитайте про DI и IoC. Очень сильно поможет пониманию как не делать жесткие зависимости, и накой существует interface (хотя это не единственное его применение). Чтива на полдня (если не меньше), зато сэкономит в будущем немало времени на разработку и понимание происходящего.
2. Не усложняйте себя жизнь. Серьезно, git был придуман для того чтобы проект можно було сопровождать и дорабатывать. Не хочется сейчас делать диалговое окно для настроек? Окей, оставляйте TODO в коде, закидывайте простыню и собирайте проект чтобы проверить что настройки в целом попадают в FileManager. Разнести один проект на 10 отедльных всегда успеете. Пока у вас пустой окно, пустая либа и наполеоновские планы.
3. в целом, раз я уже вязался в эту тему, могу еще ради приличия глянуть старые исходники. Возможно даже переделать под WPF, но это уже вам решать выкладывать ли это в общий доступ.
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 13:49  [ТС]
У меня вопросс. Как библиотеку Eador_M_of_the_B_W_Library (Ну предыдущие название DATAGame_Library) сделать WPF библиотекой NET Framework. Просто в шарпе нет такого шаблона. А NET Core не подходит.
Мне просто важно чтобы в библиотеке Eador_M_of_the_B_W_Library добавлялись окна WPF а не WinForms
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16451 / 11294 / 2892
Регистрация: 21.04.2018
Сообщений: 33,198
Записей в блоге: 2
22.04.2021, 13:52
Цитата Сообщение от Alexandr_7 Посмотреть сообщение
Ну в этом и вопрос где вызывать LoadDATAGame? Если в App то и сам объект DATAGameModel нужно выносить в App
Да.
Так как DATAGameModel у вас может быть нужен в любом UI элементе (Окне, UserControl и др.), то будет разумно его записать в одно из свойств локатора в ресурсах App.
Если он нужен в каких-то VM, то передавать ссылку на него в конструктор VM.
0
 Аватар для Alexandr_7
87 / 22 / 6
Регистрация: 29.12.2015
Сообщений: 1,904
22.04.2021, 14:05  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
Сервис/менеджер/контрол, и не связан с моделью данных? Даже не смешно. Вы сначала пишете "мне сложно работать с моим говнокодом", а когда вам предлагают вменяемое решение -- "это не правильно". Вы уверены?
Да в принципе я решил уже библиотеку назвать Eador_M_of_the_B_W_Library и просто расформировать DataGame и Файловый менеджер по полочкам.
Точнее Файловый менеджер я пока не добавлял. Мне сначало нужно решить работу самого DataGame
Но MessageService останется отдельной либой тупо потому что удобно будет ее подключить к любому проекту. Даже несмотря на то что пока что там всего 1 метод.
Цитата Сообщение от Wolfdp Посмотреть сообщение
Вас по ходу хлебом не корми, дай чего-либо "запилить в либу". Это тупо 1 окно, с N-полями в которых нужно указать значения. Если такое окно для вас "слишком сложно", то встречный вопрос -- на кой вам вообще программирование? Вам самим будет приятно пользоватся этим подельем? Каждый раз при вызове программы наблюдать картину из постоянно появляющихся окон, вместо единых настроек? Причем такое окно можно будет в одну строчку переиспользовать на главном окне, если пользователь захочет поменять параметры. Нужно добавить новое значение? Добавили в модель свойство, в окне -- новое поле. Все, ничего сложного.
Ну и так:
1. Почитайте про DI и IoC. Очень сильно поможет пониманию как не делать жесткие зависимости, и накой существует interface (хотя это не единственное его применение). Чтива на полдня (если не меньше), зато сэкономит в будущем немало времени на разработку и понимание происходящего.
2. Не усложняйте себя жизнь. Серьезно, git был придуман для того чтобы проект можно було сопровождать и дорабатывать. Не хочется сейчас делать диалговое окно для настроек? Окей, оставляйте TODO в коде, закидывайте простыню и собирайте проект чтобы проверить что настройки в целом попадают в FileManager. Разнести один проект на 10 отедльных всегда успеете. Пока у вас пустой окно, пустая либа и наполеоновские планы.
3. в целом, раз я уже вязался в эту тему, могу еще ради приличия глянуть старые исходники. Возможно даже переделать под WPF, но это уже вам решать выкладывать ли это в общий доступ.
Да увидел я как у вас просто не знаю на сколько большой в этом смысл. Добавлю потом. Мне не сложно openFileDialog и BetterFolderBrowser в отдельное окно но честно мне это окно вот вообще никаким местом не сдалось. Либо сразу открывается окно выбора либо ты тыкаешь еще кнопку чтобы открыть и ли вводишь вручную. Для когото может так и удобно а мне пока это не надо. И вообще этот проект на столько мелочный по функционалу что там в принципе 1 раз задал и забыл про это. Кнопка обновить данные это более роскошь чем необходимось в ней. Просто стер Json и все. Задавай по новой данные.
Так что пока что будет 2 диалога без объедениния в одно окно потому что так проще.

Добавлено через 2 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Да.
Так как DATAGameModel у вас может быть нужен в любом UI элементе (Окне, UserControl и др.), то будет разумно его записать в одно из свойств локатора в ресурсах App.
Если он нужен в каких-то VM, то передавать ссылку на него в конструктор VM.
Можно подробнее. Не совсем понял.

Добавлено через 2 минуты
Можно засунуть в App.xaml приложения Eador_M_of_the_B_W_Launcher
Но мы хотели эксперимент на консольном приложении делать а значит надо другое место думать. Не в приложении а в библиотеке. С другой стороны закрывать нужно приложение.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.04.2021, 14:05

Исходник файлового менеджера
Есть ли у кого нибудь исходник файлового менеджера(проводника) на C# в visual studio 2012 -2017

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

Основные функции файлового менеджера
Добрый день. Имеется начальный вид файлового менеджера (отображение структуры дисков, переходы по папкам, упорядоченные столбцы (имя,...

Каково устройство файлового менеджера?
Доброго времени суток. хочу сделать простенький файловый менеджер, что бы он мог выполнять простейшие функции, например: удаление,...

Смена файлового менеджера по умолчанию
Как сменить файловый менеджер по умолчанию на Linux mint 17 MATE? Надо чтобы все папки, включая computer:///, trash:///, домашнюю и т.д.,...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Транслитерация текста с кириллицы на латиницу (вариант №2)
Maks 13.11.2026
Обновленная версия ранее созданной обработки. Добавлено: - Проверка исходного текста на кириллицу, через обращение к стандартной функции "ТолькоКириллицаВСтроке" из общего модуля. . .
Часы с термометром и праздничным календарем
yariko 12.11.2026
Сегодня мы рассмотрим как можно сделать отличные многофункциональные часы. Итак, поставим конкретную задачу: разработать часы с календарем, двумя термодатчиками, выводом поздравительных сообщений. . .
Транслитерация текста с кириллицы на латиницу (вариант №1)
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru