Appearance
question:Форма BuyMenu.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Albion_Helper { public partial class BuyMenu : Form { private readonly ItemsProcessing itemsProcessing; public BuyMenu() { InitializeComponent(); this.FormClosed += (sender, e) => Application.Exit(); BrowserList.SmallImageList = ImageList; InventoryList.SmallImageList = ImageList; itemsProcessing = new ItemsProcessing(BrowserList, InventoryList, ImageList); itemsProcessing.LoadImagesToImageList(); List<Item> items = itemsProcessing.GetSortedItems(); itemsProcessing.PopulateBrowseList(); itemsProcessing.InitializeListViewMouseHandlers(); } private void AddToInventory_Click(object sender, EventArgs e) { if (BrowserList.SelectedItems.Count > 0) { foreach (ListViewItem item in BrowserList.SelectedItems) { // Получаем объект Item из Tag выбранного элемента. Item selectedItem = item.Tag as Item; if (selectedItem != null) { // Создаём новый элемент с правильными колонками для InventoryList. ListViewItem newItem = itemsProcessing.CreateInventoryListViewItem(selectedItem); InventoryList.Items.Add(newItem); } // Удаляем элемент из списка BrowserList. BrowserList.Items.Remove(item); } } } private void RemoveFromInventory_Click(object sender, EventArgs e) { if (InventoryList.SelectedItems.Count > 0) { // Создаём список элементов, чтобы не изменять коллекцию во время просмотра List<ListViewItem> selectedItems = new List<ListViewItem>(InventoryList.SelectedItems.Cast<ListViewItem>()); foreach (ListViewItem inventoryItem in selectedItems) { // Получаем объект Item из Tag выделенного элемента Item item = inventoryItem.Tag as Item; if (item != null) { // Создаём новый элемент для BrowserList ListViewItem browserItem = itemsProcessing.CreateBrowserListViewItem(item); BrowserList.Items.Add(browserItem); } InventoryList.Items.Remove(inventoryItem); } } } private void InventorySearch_TextChanged(object sender, EventArgs e) { string searchText = InventorySearch.Text.ToLower(); InventoryList.Items.Clear(); // Очищаем текущие отображаемые элементы // Отфильтровываем элементы по запросу и добавляем их в InventoryList var filteredItems = itemsProcessing.GetSortedItems() .Where(item => item.GetFullEnglishName().ToLower().Contains(searchText) && InventoryList.Items.Cast<ListViewItem>().Any(lvi => lvi.Tag == item)) .Select(item => itemsProcessing.CreateInventoryListViewItem(item)); foreach (var listViewItem in filteredItems) { InventoryList.Items.Add(listViewItem); } } private void BrowserSearch_TextChanged(object sender, EventArgs e) { string searchText = BrowserSearch.Text.ToLower(); BrowserList.Items.Clear(); // Очищаем текущие отображаемые элементы // Отфильтровываем элементы по запросу и добавляем их в BrowserList var filteredItems = itemsProcessing.GetSortedItems() .Where(item => item.GetFullEnglishName().ToLower().Contains(searchText) && !InventoryList.Items.Cast<ListViewItem>().Any(lvi => lvi.Tag == item)) .Select(item => itemsProcessing.CreateBrowserListViewItem(item)); foreach (var listViewItem in filteredItems) { BrowserList.Items.Add(listViewItem); } } } }
answer:Запомнил.
question:ItemsList.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace Albion_Helper { public class Item { public string EnglishName { get; set; } public string RussianName { get; set; } public string EnglishCategory { get; set; } public string RussianCategory { get; set; } public string EnglishSubcategory { get; set; } public string RussianSubcategory { get; set; } public int MinLevel { get; set; } public int MinCharm { get; set; } public int Level { get; set; } public int Charms { get; set; } public string Quality { get; set; } public string ImageFileName { get; set; } public string GetImageFileName() { string enchantmentSuffix = Charms > 0 ? "@" + Charms.ToString() : string.Empty; return "T{Level}_{ImageFileName}{enchantmentSuffix}"; } public Item(string englishName, string russianName, string englishCategory, string russianCategory, string englishSubcategory, string russianSubcategory, int minLevel, int minCharms, int level, int charms, string quality, string imageFileName) { EnglishName = englishName; RussianName = russianName; EnglishCategory = englishCategory; RussianCategory = russianCategory; EnglishSubcategory = englishSubcategory; RussianSubcategory = russianSubcategory; MinLevel = minLevel; MinCharm = minCharms; Level = level; Charms = charms; Quality = quality; ImageFileName = imageFileName; } // Методы класса Item, имитирующие некоторую локализацию и логику public string GetLocalizedCategory() { // Вставьте логику для выбора локализованной категории return EnglishCategory; } public string GetFullEnglishName() { string prefix = GetLevelPrefix(); return prefix + " " + EnglishName; } public string GetLevelPrefix() { // Вставьте логику для возвращения префикса уровня switch (Level) { case 1: return "Beginner's"; case 2: return "Novice's"; case 3: return "Journeyman’s"; case 4: return "Adept’s"; case 5: return "Expert’s"; case 6: return "Master’s"; case 7: return "Grandmaster’s"; case 8: return "Elder’s"; default: return ""; } } } public class ItemsList { // Приватное поле для хранения списка предметов public List<Item> items; public List<Item> GetItems() => items; // Конструктор класса ItemsList public ItemsList() { items = new List<Item>(); items.Add(new Item("Arcane Staff", "Арканый посох", "Weapons", "Оружие", "Magic Staffs", "Магические посохи", 3, // Минимальный уровень этого предмета 0, // Минимальный уровень чар этого предмета 3, // Текущий уровень предмета 0, // Уровень чар предмета "Normal", "MAIN_ARCANESTAFF")); items.Add(new Item("Mercenary Hood", "Капюшон наемника", "Armor", "Броня", "Leather Helmet", "Кожаный шлем", 1, // Минимальный уровень этого предмета 0, // Минимальный уровень чар этого предмета 1, // Текущий уровень предмета 0, // Уровень чар предмета "Normal", "HEAD_LEATHER_SET1")); } } }
answer:Запомнил.
question:ItemsProcessing.cs using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Albion_Helper { public class ItemsProcessing { private ListView BrowserList; private ListView InventoryList; private ImageList ImageList; private ItemsList itemsList; private int levelColumnIndex = 3; private int enchantmentColumnIndex = 4; public ItemsProcessing(ListView browserList, ListView inventoryList, ImageList imageList) { BrowserList = browserList; InventoryList = inventoryList; ImageList = imageList; itemsList = new ItemsList(); LoadImagesToImageList(); PopulateBrowseList(); InitializeListViewMouseHandlers(); } public void LoadImagesToImageList() { foreach (var item in itemsList.GetItems()) { string imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "BuyMenu", "ItemsIco", item.GetImageFileName() + ".png"); if (File.Exists(imagePath)) { using (var bmpTemp = new Bitmap(imagePath)) { ImageList.Images.Add(item.GetImageFileName(), new Bitmap(bmpTemp)); } } } } private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { ComboBox comboBox = sender as ComboBox; if (comboBox.Tag is ListViewItem listViewItem && listViewItem.Tag is Item item) { // Определяем, из какого именно ComboBox изменение пришло bool isLevelChanged = listViewItem.SubItems[levelColumnIndex].Bounds.Contains(comboBox.Bounds.Location); bool isEnchantmentChanged = listViewItem.SubItems[enchantmentColumnIndex].Bounds.Contains(comboBox.Bounds.Location); if (isLevelChanged) { int newLevel = int.Parse(comboBox.SelectedItem.ToString()); item.Level = newLevel; listViewItem.SubItems[levelColumnIndex].Text = item.Level.ToString(); // Если уровень предмета стал меньше 4, обнуляем чары if (newLevel < 4) { item.Charms = 0; // Найдите и обновите ComboBox для чаров, если он есть в текущем контексте // Возможно, потребуется пройтись по всем контролам или сохранить ссылку на ComboBox чаров listViewItem.SubItems[enchantmentColumnIndex].Text = item.Charms.ToString(); } } else if (isEnchantmentChanged && item.Level >= 4) // Проверяйте уровень перед тем, как изменять чары { item.Charms = int.Parse(comboBox.SelectedItem.ToString()); listViewItem.SubItems[enchantmentColumnIndex].Text = item.Charms.ToString(); } listViewItem.ImageKey = item.GetImageFileName(); // Обновляем иконку предмета comboBox.Visible = false; // Обязательно скрываем ComboBox после выбора listViewItem.ListView.Refresh(); // Обновляем ListView для отображения изменений } } public void PopulateBrowseList() { List<Item> items = GetSortedItems(); BrowserList.Items.Clear(); foreach (Item item in items) { ListViewItem listViewItem = CreateBrowserListViewItem(item); BrowserList.Items.Add(listViewItem); } } public ListViewItem CreateBrowserListViewItem(Item item) { ListViewItem listViewItem = new ListViewItem { ImageKey = item.GetImageFileName(), Tag = item }; listViewItem.SubItems.Add(item.EnglishName); listViewItem.SubItems.Add(item.GetLocalizedCategory()); return listViewItem; } public List<Item> GetSortedItems() { return itemsList.GetItems().OrderBy(item => item.EnglishName).ToList(); } public void InitializeListViewMouseHandlers() { BrowserList.MouseClick += (sender, e) => HandleMouseClick((ListView)sender, e); InventoryList.MouseClick += (sender, e) => HandleMouseClick((ListView)sender, e); } private void HandleMouseClick(ListView listView, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { ListViewHitTestInfo hit = listView.HitTest(e.X, e.Y); if (hit.SubItem != null) { if (listView == InventoryList) { DisplayComboBoxOrTextBox(hit); } } } } public void AddToInventory() { if (BrowserList.SelectedItems.Count > 0) { foreach (ListViewItem item in BrowserList.SelectedItems) { Item selectedItem = (Item)item.Tag; ListViewItem newItem = CreateInventoryListViewItem(selectedItem); InventoryList.Items.Add(newItem); BrowserList.Items.Remove(item); } } } public void RemoveFromInventory() { if (InventoryList.SelectedItems.Count > 0) { foreach (ListViewItem item in InventoryList.SelectedItems) { Item selectedItem = (Item)item.Tag; ListViewItem newItem = CreateBrowserListViewItem(selectedItem); BrowserList.Items.Add(newItem); InventoryList.Items.Remove(item); } } } public ListViewItem CreateInventoryListViewItem(Item item) { ListViewItem listViewItem = new ListViewItem(); listViewItem.ImageKey = item.GetImageFileName(); listViewItem.SubItems.Add(item.GetFullEnglishName()); listViewItem.SubItems.Add("1"); listViewItem.SubItems.Add(item.Level.ToString()); listViewItem.SubItems.Add(item.Charms.ToString()); listViewItem.SubItems.Add(item.GetLocalizedCategory()); listViewItem.Tag = item; return listViewItem; } private void DisplayComboBoxOrTextBox(ListViewHitTestInfo hit) { int yOffset = 65; // Смещение по вертикали // Индексы столбцов (могут быть другими - настроить под свою структуру) int quantityColumnIndex = 2; // Индекс колонки для количества int levelColumnIndex = 3; // Индекс колонки для уровня int enchantmentColumnIndex = 4; // Индекс колонки для чаров // Проверяем, что клик был по интересующим нас колонкам в InventoryList int columnIndex = hit.Item.SubItems.IndexOf(hit.SubItem); if (columnIndex == quantityColumnIndex || columnIndex == levelColumnIndex || columnIndex == enchantmentColumnIndex) { // Определяем границы ячейки и контрол для отображения Rectangle cellBounds = hit.SubItem.Bounds; cellBounds.Offset(15, yOffset); cellBounds.Height -= yOffset; // Корректируем высоту с учетом смещения Control controlToDisplay = null; // Создание и настройка TextBox для количества if (columnIndex == quantityColumnIndex) { TextBox quantityTextBox = new TextBox { Bounds = cellBounds, Text = hit.SubItem.Text, Tag = hit.Item }; quantityTextBox.Leave += TextBox_Leave; hit.Item.ListView.Parent.Controls.Add(quantityTextBox); quantityTextBox.Focus(); quantityTextBox.Leave += (sender, e) => quantityTextBox.Visible = false; quantityTextBox.KeyPress += (sender, e) => { if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) { e.Handled = true; } }; quantityTextBox.KeyDown += (sender, e) => { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return) { hit.SubItem.Text = quantityTextBox.Text; quantityTextBox.Visible = false; } }; controlToDisplay = quantityTextBox; } else { // Создание и настройка ComboBox для уровня или чаров ComboBox comboBox = new ComboBox { Bounds = cellBounds, DropDownStyle = ComboBoxStyle.DropDownList, }; comboBox.Leave += (sender, e) => comboBox.Visible = false; comboBox.SelectedIndexChanged += (sender, e) => { if (comboBox.Tag is ListViewItem listViewItem && listViewItem.Tag is Item item) { // Определяем, какое именно свойство изменилось bool isLevelChanged = listViewItem.SubItems[levelColumnIndex].Bounds.Contains(comboBox.Bounds.Location); bool isEnchantmentChanged = listViewItem.SubItems[enchantmentColumnIndex].Bounds.Contains(comboBox.Bounds.Location); if (isLevelChanged) { item.Level = int.Parse(comboBox.SelectedItem.ToString()); listViewItem.SubItems[levelColumnIndex].Text = item.Level.ToString(); if (item.Level >= 4) { comboBox.Enabled = true; // Разрешаем выбор for (int i = 0; i <= 4; i++) { comboBox.Items.Add(i.ToString()); } } else { comboBox.Enabled = false; // Запрещаем выбор comboBox.Items.Add("0"); // Добавляем единственно допустимый вариант } } else if (isEnchantmentChanged) { // Не изменяем чары, если уровень меньше 4 - они должны оставаться равными 0. if (item.Level >= 4) { item.Charms = int.Parse(comboBox.SelectedItem.ToString()); listViewItem.SubItems[enchantmentColumnIndex].Text = item.Charms.ToString(); } } listViewItem.ImageKey = item.GetImageFileName(); // Обновляем иконку предмета listViewItem.ListView.Refresh(); // Обновляем ListView для отображения изменений comboBox.Visible = false; // Скрываем ComboBox после выбора } hit.SubItem.Text = comboBox.SelectedItem.ToString(); }; // Fill the ComboBox with the right values depending on the column if (columnIndex == levelColumnIndex) { int minLevel = (hit.Item.Tag as Item)?.MinLevel ?? 1; for (int i = minLevel; i <= 8; i++) { comboBox.Items.Add(i.ToString()); } } else if (columnIndex == enchantmentColumnIndex) { for (int i = 0; i <= 4; i++) { comboBox.Items.Add(i.ToString()); } } // Set selected value comboBox.SelectedItem = hit.SubItem.Text; controlToDisplay = comboBox; } if (controlToDisplay != null) { hit.Item.ListView.Parent.Controls.Add(controlToDisplay); controlToDisplay.BringToFront(); controlToDisplay.Visible = true; controlToDisplay.Focus(); } } } private void TextBox_Leave(object sender, EventArgs e) { TextBox tb = sender as TextBox; if (tb != null) { ListViewItem item = (ListViewItem)tb.Tag; if (item != null && item.ListView != null) { // Здесь номер колонки для количества - 2 (или другой индекс, если структура ListView иная) item.SubItems[2].Text = tb.Text; } item.ListView.Focus(); // Перемещаем фокус на ListView tb.Dispose(); // Уничтожаем TextBox } } } }
answer:Запомнил. Задачи, которые вы описали, требуют доработки логики работы с элементами пользовательского интерфейса. Так как артефакты кода для `ComboBox_SelectedIndexChanged` в приложенных файлах не были найдены, я предположу, что данный метод должен быть добавлен в класс `ItemsProcessing`, и в него необходимо включить логику обновления иконки и ограничения по выбору чаров в зависимости от уровня предмета. В продолжение предположения, что метод `ComboBox_SelectedIndexChanged` существует, но его просто нет в прикрепленных кодах, вы должны будете учесть следующее: 1. Чтобы запретить выбор чар для предмета с уровнем меньше 4, вам нужно изменить код инициализации `ComboBox` для чаров так, чтобы при выборе уровня меньше 4 комбо-бокс деактивировался или не позволял выбирать значения отличные от 0. 2. Для обновления иконки в зависимости от выбранного уровня и чар необходимо гарантировать, что у каждого предмета (`Item`) есть правильно сформированный путь к файлу иконки, который будет изменяться при изменении выбранных значений. Скорректирую метод `ComboBox_SelectedIndexChanged` для выполнения этих задач: ```csharp private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { ComboBox comboBox = sender as ComboBox; if (comboBox != null && comboBox.Tag is ListViewItem listViewItem && listViewItem.Tag is Item item) { int oldValue = (comboBox.Name == "LevelComboBox") ? item.Level : item.Charms; int newValue = int.Parse(comboBox.SelectedItem.ToString()); if (comboBox.Name == "LevelComboBox") { item.Level = newValue; listViewItem.SubItems[levelColumnIndex].Text = item.Level.ToString(); } else if (comboBox.Name == "CharmComboBox" && item.Level >= 4) { item.Charms = newValue; listViewItem.SubItems[enchantmentColumnIndex].Text = item.Charms.ToString(); } listViewItem.ImageKey = item.GetImageFileName(); // Обновляем иконку предмета comboBox.Visible = false; // Скрываем ComboBox после выбора // Обновляем ComboBox для чаров, если уровень изменился if (comboBox.Name == "LevelComboBox") { ComboBox charmComboBox = listViewItem.ListView.Controls["CharmComboBox"] as ComboBox; if (charmComboBox != null) { charmComboBox.Items.Clear(); if (item.Level >= 4) { for (int i = item.MinCharm; i <= 3; i++) { charmComboBox.Items.Add(i.ToString()); } charmComboBox.Enabled = true; } else { charmComboBox.Items.Add("0"); // Если уровень меньше 4, чары могут быть только 0 charmComboBox.SelectedItem = "0"; charmComboBox.Enabled = false; } } } } } ``` Обратите внимание, что я предположил наличие `Name` у `ComboBox`, которые определяют, относится ли он к уровню или чарам. Вам возможно потребуется адаптировать этот код для точного соответствия вашему проекту, так как имена контролов и их индексация могут отличаться. Кроме того, нету обработчика `ComboBox_Leave`, который бы прятал `ComboBox` при уходе фокуса с него. Рассмотрите добавление такого обработчика, если это ещё не реализовано в проекте. Для полной интеграции этого кода в ваш проект может потребоваться более глубокая доработка и тестирование. Если у вас есть дополнительные вопросы или недопонимание какого-то аспекта, не стесняйтесь задавать их.
question:Обрати внимание что на ComboBox_SelectedIndexChanged ничто не ссылается, следовательно что-то менять надо в методе DisplayComboBoxOrTextBox
answer:Понял вас, давайте скорректируем метод `DisplayComboBoxOrTextBox` в классе `ItemsProcessing` таким образом, чтобы он не только отображал `ComboBox`, но и выполнял необходимые изменения и ограничения. Ниже представлен обновленный код метода `DisplayComboBoxOrTextBox`, где добавлены проверки и корректировки для изменения доступных вариантов `ComboBox` в зависимости от уровня предмета и обработка события изменения выбора: ```csharp private void DisplayComboBoxOrTextBox(ListViewHitTestInfo hit) { // ... оставшийся код ... // Создание и настройка ComboBox для уровня или чаров ComboBox comboBox = new ComboBox { Bounds = cellBounds, DropDownStyle = ComboBoxStyle.DropDownList, }; // Фильтрация вариантов и настройка ComboBox в зависимости от колонки if (columnIndex == levelColumnIndex) { for (int i = 1; i <= 8; i++) { comboBox.Items.Add(i.ToString()); } } else if (columnIndex == enchantmentColumnIndex) { // Изначально запрещаем выбор чар, будем активировать ниже, если уровень >= 4 comboBox.Enabled = false; } // Отображение ComboBox hit.Item.ListView.Parent.Controls.Add(comboBox); comboBox.BringToFront(); comboBox.Visible = true; comboBox.Focus(); // Установка текущего значения в ComboBox comboBox.SelectedItem = hit.SubItem.Text; // Настройка события на изменение выбранного элемента comboBox.SelectedIndexChanged += (sender, e) => { // Получаем текущий выбранный предмет Item item = hit.Item.Tag as Item; if (comboBox.SelectedIndex != -1 && item != null) { int selectedValue = int.Parse(comboBox.SelectedItem.ToString()); if (columnIndex == levelColumnIndex) { // Обновление уровня предмета и активация/деактивация ComboBox чар item.Level = selectedValue; // Получаем ComboBox для чар, если он находится в родительских контролах Control[] enchantmentComboBoxes = hit.Item.ListView.Parent.Controls.Find("CharmComboBox", true); ComboBox enchantmentComboBox = enchantmentComboBoxes.FirstOrDefault() as ComboBox; if (item.Level < 4) { // Запрет на выбор чар и сброс на 0 if (enchantmentComboBox != null) { enchantmentComboBox.Enabled = false; enchantmentComboBox.SelectedIndex = enchantmentComboBox.FindStringExact("0"); } hit.Item.SubItems[enchantmentColumnIndex].Text = "0"; } else { // Разрешение на выбор чар if (enchantmentComboBox != null) { enchantmentComboBox.Items.Clear(); for (int i = 0; i <= 3; i++) { enchantmentComboBox.Items.Add(i.ToString()); } enchantmentComboBox.Enabled = true; hit.Item.SubItems[enchantmentColumnIndex].Text = enchantmentComboBox.SelectedItem.ToString(); } } // Обновление отображаемого названия и уровня hit.Item.SubItems[columnIndex].Text = item.Level.ToString(); // Обновление уровня в списке } else if (columnIndex == enchantmentColumnIndex && item.Level >= 4) { // Обновление чар предмета item.Charms = selectedValue; hit.Item.SubItems[columnIndex].Text = item.Charms.ToString(); // Обновление чаров в списке } // Обновление иконки предмета hit.Item.ImageKey = item.GetImageFileName(); } comboBox.Visible = false; // Скрытие ComboBox после выбора }; // ... оставшийся код ... } ``` В этом фрагменте кода я добавил обработчик событий `comboBox.SelectedIndexChanged`, который обновит информацию о предмете в соответствии с выбранными значениями. Помимо этого, также добавлено включение или отключение `ComboBox` для чар, когда выбранный уровень предмета меньше четырех. Кроме того, предполагается, что у `ComboBox` для чар есть имя (Name) "CharmComboBox"; если это не так, вам следует добавить эту логику, чтобы обеспечить корректное взаимодействие между выбором уровня и доступностью чар. Обратите внимание, что приведенный метод `DisplayComboBoxOrTextBox` опирается на структуру вашего GUI и именования контролов, которые могут требовать вашей адаптации. Если в коде уже есть другие методы с похожим функционалом, следует провести объединение логики для избежания дублирования и конфликтов.